Open harvinders opened 10 years ago
you can with a workaround and adjusting Specflow.reporting slightly. First you need another class to inherit from Steps - in my snippet below thats simply: public class MetaSteps : Steps { }
Secondly you need to set some methods to public in Specflow.Reporting (those that are shown as inaccessable using the snippet below)
Using that, i can use the following method in my GlueCode, that does the trick:
public void ExecuteGherkin(string gherkin, string stepType, params object[] args) {
Action action = new Action(DummyMethod);
var currentSteps = new Dictionary<Reporter, Step>();
var starttime = DateTime.Now;
foreach (var reporter in Reporters.GetAll()) {
currentSteps.Add(reporter, reporter.CurrentStep);
var step = Reporters.CreateStep(starttime, action.Method, args);
step.Title = gherkin + ".";
// wird er an den aktuellen Step angehängt, so hat das Stepergebnis wiederum Stepergebnisse -> landet im json auf einer Ebene zu tief
//var stepContainer = reporter.CurrentStep ?? reporter.CurrentScenarioBlock;
var stepContainer = reporter.CurrentScenarioBlock;
stepContainer.Steps.Add(step);
reporter.CurrentStep = step;
Reporters.OnStartedStep(reporter);
}
Exception actionException = null;
try {
// eigentliche Ausführung
if (stepType == StepType.Given)
MetaSteps.Given(gherkin);
else if (stepType == StepType.When)
MetaSteps.When(gherkin);
else if (stepType == StepType.Then)
MetaSteps.Then(gherkin);
} catch (Exception ex) {
if (ex is TargetInvocationException && ex.InnerException != null) {
// Exceptions thrown by ReportingMessageSink are wrapped in a TargetInvocationException
actionException = ex.InnerException;
} else {
actionException = ex;
}
} finally {
var endtime = DateTime.Now;
TestResult testResult;
if (actionException is PendingStepException) {
testResult = TestResult.Pending;
} else if (actionException != null) {
testResult = TestResult.Error;
} else {
testResult = TestResult.OK;
}
foreach (var reporter in Reporters.GetAll()) {
reporter.CurrentStep.EndTime = endtime;
reporter.CurrentStep.Result = testResult;
reporter.CurrentStep.Exception = actionException.ToExceptionInfo();
// finish step (take screenshot)
reporter.CurrentStep.UserData = new {
Screenshot = TakeScreenshot()
};
reporter.CurrentStep = currentSteps[reporter];
}
}
}
To avoid null reference errors (a different issue) you also have to hand through the Specflow hooks, that dont seem to work properly (also using the modified Specflow.Reporting lib):
[BeforeScenarioBlock]
public static void BeforeScenarioBlock() {
SpecFlow.Reporting.Reporters.BeforeScenarioBlock();
}
[BeforeScenario]
public static void BeforeScenario() {
SpecFlow.Reporting.Reporters.BeforeScenario();
}
[BeforeFeature]
public static void BeforeFeature() {
SpecFlow.Reporting.Reporters.BeforeFeature();
}
[AfterScenarioBlock]
public static void AfterScenarioBlock() {
etc etc - just do that for all
all the posted code is part of a class that all of my GlueCode classes inherit from
maybe this helps - works for me - feel free to ask
I attempted to copy the provided solution but some of the code was outdated. Instead I found another workaround that seems to work for me.
The premise is this:
Code snippets below:
using BoDi;
using TechTalk.SpecFlow;
using TechTalk.SpecFlow.Infrastructure;
namespace StepDefinitions
{
public class SubSteps : Steps
{
public SubSteps(IObjectContainer objectContainer)
{
((IContainerDependentObject)this).SetObjectContainer(objectContainer);
}
}
}
using SpecResults;
using SpecResults.Json;
using TechTalk.SpecFlow;
namespace StepDefinitions
{
[Binding]
public class BaseStepDefinitions : ReportingStepDefinitions
{
protected SubSteps subSteps;
// Initialize SubSteps class
public BaseStepDefinitions()
{
subSteps = new SubSteps(ScenarioContext.Current.ScenarioContainer);
}
[Then(@"I login to the website")]
public void ThenILoginToTheWebsite()
{
// Navigate browser
subSteps.Then("I navigate the browser to http://google.com");
}
[Then(@"I navigate the browser to ([^\s]+)")]
public void ThenINavigateTheBrowserTo(string url)
{
// Logic to navigate browser
...
}
}
}
This solution seems to work for me, however when calling the subSteps the steps are not added to the report.
If we extend the class from
ReportingStepDefinitions
then we can't use the feature described at Calling Steps from Step Definitions as it requires us to extend the class fromSteps