AfterFeature hook not working properly in specFlow - c#

I have 2 feature files with 2 step definition classes.Each class has methods with [AfterFeature] hook.While executing feature2, the method defined under [AfterFeature] hook in step definition file for feature1 gets invoked.

The After Feature Hook in spec-flow is designed to be run after each feature.
https://specflow.org/documentation/Hooks/
Shows the details of the hooks that can be used and they are designed to all be run before or after.
looking over their Definition you could Try adding a class level Scope Attribute ( Listed Here Binding Documentation) to the class containing the AfterFeature step this may limit it but alas this is not the intended purpose. So i wouldn't overly expect this to work.
sorry its not the best answer in the world

Related

Override a step declaration in SpecFlow?

So at my job we have a core SpecFlow library that our different teams can use for their automation. This library has some declared steps.
For example, the library might have something like this:
When I click the button
However, let's say I want to define my own step declaration that uses that exact same wording. Is it possible to override it?
As #Grasshopper wrote, the step definition are global.
But you could use Scopes to overwrite it.
See http://www.specflow.org/documentation/Scoped-Bindings/
In this case do not forget to specify on every scenario the tag or the original step definition will be called.
It would be a very bad idea to do this, as any scenario that uses this step and fails will be very much harder to understand and debug.
In general using generic library steps in scenarios is also not such a good idea. Scenarios should not contain generic steps or descriptions of HOW things are done. Instead they should contain steps specific to your business context, and these should describe WHAT is being done and WHY its being done.
So instead of
When I click on sign in
And I fill in my email with ...
...
we get the much simpler and more abstract
When I sign in
which is all about WHAT we are doing, and nothing about HOW we are doing it.
You will get a DuplicateStepException if you have a same step (in your case - When I click the button) twice either in the same step definition file or another one. Even if you use a given or then annotation. This is because the step definitions are loaded globally thus resulting in conflict.
Also you cannot extend a stepdefinition or hook containing file as cucumber will throw an error that this is not acceptable. Thus no way you can override behaviour by inheritance.
You will need to write a different step all together, or if possible pass the button as a parameter to the existing step and put in the logic if you are allowed to modify the library code.

Is there any way to auto run some code in DLL?

I have some DLL from third party that I need to license. It has some method that I must call from my own DLL. My DLL is referenced in couple of projects and I don't want to make changes to every hoster. Is there any method that I can use within my DLL which will call some method in my DLL? Like add some static class or constructor but without explicit call to that class from hosters? I am not sure if I am explaining it clearly. Please ask questions if needed.
ThirdPartyType license = new ThirdPartyType();
license.Load("license.xml");
This is a piece of licensing code that I want to place in my DLL and call it within the same DLL.
At the low level, the runtime supports "module initializers". However, C# does not provide any way of implementing them, so the closest you can manage is a static constructor ("type initializer") or just a regular constructor.
However, it is probably a bad idea to hook your licencing into either a module initializer or a type initializer, as you don't know when they will run, and it could impact code that wasn't going to access your lib. It is somewhat frowned upon to take someone's app down because your licensing code decided it was unhappy - especially if your library wasn't actively being invoked at the time.
As such: I suggest the most appropriate place to do this is in either a constructor, or a post-construction Initialize(...) method (with the tool refusing to work unless supplied with valid details).

Why is my Specflow [AfterTestRun] hook called twice

[AfterTestRun]
This hook for me is being called twice.
My C# code is correct and at the end of each Scenario I am saving my results to a Concurrent Bag.
Then I use the [AfterTestRun] hook to call the Concurrent Bag and save the data to a database. I see duplicated data, so I assume it’s being called twice.
Additional Info:
I am using SpecRun to run my tests in parallel with the following profile
Execution stopAfterFailures="1" retryCount="0" testThreadCount="3" testSchedulingMode="Sequential"
Packages Installed
SpecFlow Version 2.0.0
SpecRun.SpecFlow 1.3.0
SpecRun.Runner 1.3.0
I am using SpecRun.SpecFlow to run my tests.
Also, how will this hook behave if one has multiple scenarios within each feature? Currently I have 1.
Thanks
Steps are global in specflow, inheritance to get step reuse is unnecessary. In fact if you do inherit step classes the the steps they contain end up being duplicated, and you see the issue you have here. See this answer for additional details.
the simple solution is to place the [BeforeScenario] methods into their own class, and do not have your step classes inherit this. If you need to share state between your steps and your before/after scenarios then use one of the state sharing techniques outlined here

Specflow Feature files with same steps causing multiple browser instances to launch

I have at least 3 .feature files in my C# Specflow tests project in which I have the step, for instance:
Given I am at the Home Page
When I first wrote the step in the file Feateure1.feature and created the step method, I placed it in a step file, let's say, Steps1.cs, which inherits from a base class that initializes a FirefoxDriver. All my StepsXXXX.cs classes inherit from this base class.
Then, I wrote Feature2.feature, which also has a step Given I am at the Home Page. And the step was automaticaly bound to the one in Steps1.cs
'Till now, no problem. That's pretty much what I wanted - to have reusable steps throughout the test project. But the problem is, whenever I'm running a scenario that has steps in diferent StepsXXXX files, I get various browser instances running.
======
I'm pretty sure this is due to the fact that My StepsXXXX (binding classes) all inherit from this base class that has a IWebDriver of its own, and when the step is called, everything else (including the before/after scenario methods) is called. But I can't figure out how to work around this.
I still want reusable steps. I tried to put these steps in the base class, but it did not work.
I thought of changing the bindings too, but specflow uses meaningfull strings to do so, and I don't want to change them to misleading strings.
Has anyone stumbled across this?
Any help is really appreciated.
You can use Scoped bindings using [Scope(Tag = "mytag", Feature = "feature title", Scenario = "scenario title")] to referred on specific scenario or feateure like this:
Feature: Feateure1
Scenario: demo
Given I am at the Home Page
When ....
[Binding, Scope(Feature = "Feateure1")]
public class Steps1{
[Given(#"Given I am at the Home Page")]
public void GivenIAmAtTheHomePage(){
{ }
}
Feature: Feateure2
Scenario: demo
Given I am at the Home Page
When ....
...
[Binding,Scope(Feature = "Feateure2")]
public class Steps2{
[Given(#"Given I am at the Home Page")]
public void GivenIAmAtTheHomePage(){
{ }
}
The problem is that SpecFlow bindings don't respect inheritance. All custom attributes are considered global, and so all SpecFlow does is search for a list of classes with a [Binding]then build up a dictionary for all the [Given]/[When]/[Then]s so that it can evaluate them for a best match. It will then create an instance of the class (if it hasn't already done so) and call the method on it.
As a result your simple cases all stay in the Steps1 class, because its the first perfect match. Your more complicated cases start instantiating more classes, hence multiple browsers, And your attempt to refactor won't work because your abstract base class doesn't have a [Binding] on it.
I'd probably start by flattening all your step class hierarchy, into one big AllSteps.cs class. This may seem counter-productive, but all you are really doing is arranging the code just how the current bindings appear to your SpecFlow features. This way you can start to refactor out the overlaps between the different GWT bindings.
At the moment your bindings are arranged around the scenarios. What you will need to do is refactor them around your functionality. Have a read of Whose Domain is it anyway? before you start and this will probably give you some good ideas. Then have a look at Sharing-Data-between-Bindings on the SpecFlow documentation to work out how to link between your new steps classes.
i think this is a lot more simple than the question and answers here make it out to be. there are really two questions at play here:
AISki gave you the right answer in the link to documentation about specflow context, but it was not really presented as the answer and there was distraction in presenting an inferior answer as the actual answer.
the answer as to the behavior you see is that you should expect exactly what is happening with the way you set things up. if you have multiple binding classes that create browser instances (and you do if they all have a common base that creates a browser instance) and they have matches in your features, you should expect multiple browser instances.
The answer for what you intend (a single browser shared among your steps) is that you should use the context feature of specflow to control the dependency on a browser instance. this amounts to dependency injection. your step definition classes should take a constructor dependency on something that creates your browser instance - specflow manages dependencies for you and you'll get a new instance for the first of your classes created and then the same one after that.
https://github.com/techtalk/SpecFlow/wiki/Sharing-Data-between-Bindings
I facing the same issue.
I wanted to have one feature file that will call steps in different cs classes. The issue came across when I want to setup and tear down for each scenario.
Using step class constructor and Dispose() not possible because the scenario uses more than one step class which I don't want to 'setup' multiple time in a scenario.
Using [BeforeScenario] and [AfterScenario] for both step classes also makes the runner run the before and after methods in both class that makes it setup run twice.
So what I was done is create another third class called something like BrowserScenarioSetup put the before and after scenario class in it to setup a browser for the scenario and assign to ScenarioContext.Current dictionary. When the test run, only one browser created for a scenario and I can use scenario steps defined in any class but just uses Scenario.Context.Current to get the browser instance.
I can make both step classes have a base step class and create a short method to get browser instance (or any shared instance created in setup) just to hide Scenario.Context.Current
Finally I can mark [BeforeScenario("Browser", "IE")] and use #Browser and #IE in a feature or scenario to only call this setup method in suitable context.

How to programmatically insert code into assembly

I have an .net assembly at C#. I have both: binary and source which has no logger, for example.
All I need is to insert property which will be initialised specific logger. Then I need to introduce logger invoker in all methods. The first way - is manually write property and their invokes. And the second way - is to write another class\method (I suppose in the same assembly) which will do it automatically.
Is it possible? Any suggestions?
I think it is possible, cause it was one of the questions at the interview. But there is no proof that this is possible, and they wanted to hear "no, do this manually".
This is what we call in architectural terms a 'cross cutting concern'. Logging is something that straddles many aspects of an application.
There are features to take care of it in the Microsoft Enterprise Library. The part you want is the Policy Injection library. You can then specify, in the config, methods to match (based on method name/structure) and a function to be called. In this way you can include logging as a proper cross-cutting concern of your app, rather than something which must be manually coded into every method.
It is not possible to alter the execution of a method without altering the source code and recompiling. You could write a wrapper class that would expose all classes and methods which would first call your logger and then the methods, but that's not what they asked.
So the answer to their question is 1. is possible, 2. isn't possible, and if you would have to add logging support, you would need to add it to each method manually.

Categories