#1 .NET BDD Framework. SpecFlow automates your testing & works with your existing code. Find Bugs before they happen. Behavior Driven Development helps developers, testers, and business representatives to get a better understanding of their collaboration
SpecFlow Section in app.config or content of specflow.json
No response
Issue Description
I am using specflow runner report + Extent report in my project
When i dont execute tests in parallel Extent report is generated properly, but when i set the testThreadCount=3 in default.srprfile, the Extent report does not give the complete report, out of 5 scenarios executed it prints only 3 or 2 or sometimes 1 scenario report.
Attached below my Extent reporting hooks. Please let me know how to fix this issue.
using System;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using AventStack.ExtentReports;
using AventStack.ExtentReports.Gherkin.Model;
using AventStack.ExtentReports.MarkupUtils;
using AventStack.ExtentReports.Reporter;
using BoDi;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using SFramework.APIServices.Services;
using SFramework.ParallelConfig;
using TechTalk.SpecFlow;
namespace SciexOneOmicsFramework.CommonServices
{
[Binding]
public sealed class ExtentReportHooks
{
private readonly OneOmicsWorld _oneomicsWorld;
private static bool _extentSetting;
private static ExtentReports _extentReport;
[ThreadStatic] private static ExtentTest _scenario;
public static Stopwatch Timer = new();
[ThreadStatic] private static ExtentTest FeatureName;
private static string _driverPath;
private string _logMessage;
public IMarkup JsonDataPrinter { get; private set; }
private static readonly Stopwatch Stopwatch = new();
private static bool _jsonPrinter;
private static bool _isUIAutomation;
[ThreadStatic] private static ScenarioContext _scenarioContext;
public ExtentReportHooks(OneOmicsWorld world)
{
_oneomicsWorld = world;
}
[BeforeTestRun(Order=0)]
public static void InitializeExtentBeforeTestRun()
{
_driverPath = Environment.GetEnvironmentVariable("EXPECTED_FOLDER_PATH");
var ac = new AppConfigDataReader();
_extentSetting = ac.ExtentReportSetting;
_isUIAutomation = ac.UISetting;
if (_extentSetting)
{
_extentReport = new ExtentReports();
_extentReport.AttachReporter(ExtentReportPathConfig());
}
}
[AfterTestRun(Order = 0)]
public static void PublishReport()
{
if (_extentSetting) _extentReport.Flush();
}
[BeforeFeature(Order = 0)]
public static void BeforeFeature(FeatureContext featureContext)
{
FeatureName = _extentReport.CreateTest<Feature>(featureContext.FeatureInfo.Title);
}
[BeforeScenario(Order = 0)]
public void Extent_BeforeScenario(ScenarioContext scenarioContext, ObjectContainer objectContainer)
{
_oneomicsWorld.ObjectContainer = objectContainer;
// _oneomicsWorld.ScenarioContext = scenarioContext;
_scenarioContext = scenarioContext;
var driverPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
Timer.Restart();
_scenario = FeatureName.CreateNode<Scenario>(_scenarioContext.ScenarioInfo.Title);
}
[AfterScenario(Order = 1)] // Order is not given as zero because, zero is used in all the stepdefination class during teardown/delete of oneomics objects created
public void AfterScenario()
{
Timer.Stop();
Stopwatch.Stop();
}
[AfterStep(Order = 0)]
public void PrintScenariosAndScenarioStatusInReport()
{
if (_extentSetting)
{
var stepType = _scenarioContext.StepContext.StepInfo.StepDefinitionType.ToString();
var pInfo = typeof(ScenarioContext).GetProperty("ScenarioExecutionStatus",
BindingFlags.Instance | BindingFlags.Public);
if (!(pInfo is null))
{
var getter = pInfo.GetGetMethod(true);
var testResult = getter.Invoke(_scenarioContext, null);
if (_scenarioContext.TestError == null)
{
PassSteps(stepType);
}
else if (_scenarioContext.TestError != null)
{
if (_isUIAutomation)
FailStepsWithImage(stepType);
else
FailSteps(stepType);
}
if (testResult.ToString() == "StepDefinitionPending") PendingSteps(stepType);
}
_logMessage = "";
}
}
public void PendingSteps(string stepType)
{
if (stepType == "Given")
_scenario.CreateNode<Given>(_scenarioContext.StepContext.StepInfo.Text)
.Skip("Step Definition Pending");
else if (stepType == "When")
_scenario.CreateNode<When>(_scenarioContext.StepContext.StepInfo.Text)
.Skip("Step Definition Pending");
else if (stepType == "Then")
_scenario.CreateNode<Then>(_oneomicsWorld.ScenarioContext.StepContext.StepInfo.Text)
.Skip("Step Definition Pending");
}
public void FailSteps(string stepType)
{
if (stepType == "Given")
_scenario.CreateNode<Given>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message).Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
else if (stepType == "When")
_scenario.CreateNode<When>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message).Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
else if (stepType == "Then")
_scenario.CreateNode<Then>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message).Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
}
public void FailStepsWithImage(string stepType)
{
var screenCapture = CaptureScreenShotOnFailure(_oneomicsWorld.Driver, _scenarioContext.ScenarioInfo.Title.Trim());
if (stepType == "Given")
_scenario.CreateNode<Given>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message, screenCapture);
else if (stepType == "When")
_scenario.CreateNode<When>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message, screenCapture);
else if (stepType == "Then")
_scenario.CreateNode<Then>(_scenarioContext.StepContext.StepInfo.Text)
.Fail(_scenarioContext.TestError.Message, screenCapture);
}
public void PassSteps(string stepType)
{
if (stepType == "Given")
{
if (_jsonPrinter)
{
_scenario.CreateNode<Given>(_scenarioContext.StepContext.StepInfo.Text)
.Log(Status.Info, _oneomicsWorld.ExtentReport.JsonDataPrinter);
_jsonPrinter = false;
}
else
{
_scenario.CreateNode<Given>(_scenarioContext.StepContext.StepInfo.Text)
.Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
}
}
else if (stepType == "When")
{
_scenario.CreateNode<When>(_scenarioContext.StepContext.StepInfo.Text)
.Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
}
else if (stepType == "Then")
{
_scenario.CreateNode<Then>(_scenarioContext.StepContext.StepInfo.Text)
.Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
}
else if (stepType == "And")
{
_scenario.CreateNode<And>(_scenarioContext.StepContext.StepInfo.Text)
.Log(Status.Info, _oneomicsWorld.ExtentReport._logMessage);
}
}
public void LogInfoBlock(string jsonMessage)
{
_jsonPrinter = true;
JsonDataPrinter = MarkupHelper.CreateCodeBlock(jsonMessage, CodeLanguage.Json);
}
public void LogInfo(string message)
{
_logMessage = Convert.ToString(message);
}
public static MediaEntityModelProvider CaptureScreenShotOnFailure(RemoteWebDriver driver, string name)
{
var screenShot = ((ITakesScreenshot)driver).GetScreenshot().AsBase64EncodedString;
return MediaEntityBuilder.CreateScreenCaptureFromBase64String(screenShot).Build();
}
}
SpecFlow Version
3.9.7
Which test runner are you using?
SpecFlow+ Runner
Test Runner Version Number
3.9.7
.NET Implementation
.NET 5.0
Project Format of the SpecFlow project
Classic project format using
packages.config
.feature.cs files are generated using
SpecFlow.Tools.MsBuild.Generation NuGet package
Test Execution Method
Visual Studio Test Explorer
SpecFlow Section in app.config or content of specflow.json
No response
Issue Description
I am using specflow runner report + Extent report in my project When i dont execute tests in parallel Extent report is generated properly, but when i set the testThreadCount=3 in default.srprfile, the Extent report does not give the complete report, out of 5 scenarios executed it prints only 3 or 2 or sometimes 1 scenario report. Attached below my Extent reporting hooks. Please let me know how to fix this issue. using System; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using AventStack.ExtentReports; using AventStack.ExtentReports.Gherkin.Model; using AventStack.ExtentReports.MarkupUtils; using AventStack.ExtentReports.Reporter; using BoDi; using OpenQA.Selenium; using OpenQA.Selenium.Remote; using SFramework.APIServices.Services; using SFramework.ParallelConfig; using TechTalk.SpecFlow; namespace SciexOneOmicsFramework.CommonServices { [Binding] public sealed class ExtentReportHooks { private readonly OneOmicsWorld _oneomicsWorld; private static bool _extentSetting; private static ExtentReports _extentReport; [ThreadStatic] private static ExtentTest _scenario; public static Stopwatch Timer = new(); [ThreadStatic] private static ExtentTest FeatureName; private static string _driverPath; private string _logMessage; public IMarkup JsonDataPrinter { get; private set; } private static readonly Stopwatch Stopwatch = new(); private static bool _jsonPrinter; private static bool _isUIAutomation;
}
Default.srprofile <?xml version="1.0" encoding="utf-8"?>
Steps to Reproduce
.
Link to Repro Project
No response