Cucumber - #BeforeStep only for that StepDef class - java

I am using #BeforeStep in my step definitions, and would like to understand how it actually works.
Let's say, I have 2 step definitions SampleStepDef1 and SampleStepDef2
public class SampleStepDef1 {
#BeforeStep
public void beforeStep() {
System.out.println("Before Step -- SampleStepDef1");
}
#Given("just a gherkin step1 - app1")
public void just_a_gherkin_step1_app1() {
//implementations
}
}
public class SampleStepDef2 {
#BeforeStep
public void beforeStep() {
System.out.println("Before Step -- SampleStepDef2");
}
#Given("just another gherkin step1 - app2")
public void just_a_gherkin_step2_app2() {
//implementations
}
}
And My Gherkins looks like
Scenario: Try Epic HyperDrive
Given just a gherkin step1 - app1
And just a gherkin step2 - app1
Not sure if this was the design by cucumber-jvm; When I execute, the BeforeStep from both classes are executing but my gherkin doesn't have any steps implemented part of another class - StepDef2. I wonder if it's possible to make a BeforeStep execute only when a step def from that particular class executes.
May be a silly question, just wondering why is it so. Appreciate any clarifications or suggestions.
Note:- I am not looking for filter by tags.

Seems, the decision been taken already so the hooks should be called based on packages, not respect to classes.
More detailed conversation in this thread.
https://github.com/cucumber/cucumber-jvm/issues/1005

Related

Cucumber 4: Implement Global Hooks

I'm new to Cucumber BDD testing v4.1.
Questions:
How to impelement before(setup) method in Cucumber 4 (DAO, Spring)?
Please help. Thanks.
Cucumber Hooks – Where to use #Before
#Before, in its most basic usage, allows you to run a block of code before every scenario. Normally in Cucumber, we tend to do the initialization related things – such as object initialization, data setup etc in the Given statement. Because of this a lot of people don’t see the need of using Cucumber’s #Before. But you can use #Before to make in an entry in your reporting that a new scenario is being executed. Since #Before always runs before every scenario, you can use this in your reports to clearly depict when a scenario starts executing.
It’s not necessary that you add #Before in each feature file. Just add it in any one feature file and let Cucumber do its job. Cucumber will figure out where you have saved #Before and then it will use it before all the scenarios. To make your reporting bit more useful and easy to understand, you can actually write the scenario name as well in the report. The Java code for this is given below –
#Before
public void before(Scenario scenario) {
System.out.println("------------------------------");
System.out.println("Starting - " + scenario.getName());
System.out.println("------------------------------");
}
Cucumber API provides an Interface called Scenario, using which you can get can instance of this class. In the above code, we have just used the getName() method of this interface to print the scenario name in our log.
Test Hooks with Single Scenario (Example):
Feature File
Feature: Test Hooks
Scenario: This scenario is to test hooks functionality
Given this is the first step
When this is the second step
Then this is the third step
Step Definitions:
package stepDefinition;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class Hooks_Steps {
#Given("^this is the first step$")
public void This_Is_The_First_Step(){
System.out.println("This is the first step");
}
#When("^this is the second step$")
public void This_Is_The_Second_Step(){
System.out.println("This is the second step");
}
#Then("^this is the third step$")
public void This_Is_The_Third_Step(){
System.out.println("This is the third step");
}
}
Hooks
package utilities;
import cucumber.api.java.After;
import cucumber.api.java.Before;
public class Hooks {
#Before
public void beforeScenario(){
System.out.println("This will run before the Scenario");
}
#After
public void afterScenario(){
System.out.println("This will run after the Scenario");
}
}
EDIT:
Workaround mentioned in Issue #515 and elsewhere is to use JUnit‘s #BeforeClass and #AfterClass annotations in the runner class, like this:
#RunWith(Cucumber.class)
#Cucumber.Options(format = {
"html:target/cucumber-html-report",
"json-pretty:target/cucumber-json-report.json"})
public class HooksTest {
#BeforeClass
public static void setup() {
System.out.println("Ran the before");
}
#AfterClass
public static void teardown() {
System.out.println("Ran the after");
}
}
Note: While #BeforeClass and #AfterClass may look like the cleanest solution at first, they are not very practical to use. They work only when Cucumber-JVM is set to use the JUnit runner. Other runners, like TestNG, the command line runner, and special IDE runners, won’t pick up these hooks. Their methods must also be are static and would need static variables or singletons to share data anyway.
to run JUnit test cases from the command line
I got the answers already which is implement ConcurrentEventListener.

How to run a method after passing through a tag in the feature file?

I have a scenario in my feature file that contains two tags
#tag1, #tag2
Scenario: This is a test
Given I open the website
When I log in
Then the account page is open
Now #tag is part of a cucumber serenity runner and this works in isolation (before the implementation of #tag2):
#RunWith(CucumberWithSerenity.class)
#CucumberOptions(features="...features/", glue = {".../steps"}, tags = {"#tag1"} )
public class Tag1Runner extends Hooks {
#BeforeClass
public static void startAppium() {
AppiumServerController.startAppiumServer();
}
#AfterClass
public static void stopAppium() {
AppiumServerController.stopAppiumServer();
}
Now what I also want to do is run #tag2, but this only runs after the test has been completed. This is because the method that occurs in #tag2 should not be part of the scenario to test, but should complete a clean up after the test has ran.
Now if I include the following method below, when I run the feature file as it is displayed above, nothing happens.
How can I implement #tag2 to work as mentioned?
public class Hooks{
#After("#tag2")
public void completeCleanUp() {
//code to perform clean up...
}
}
If you are trying to run an After hook after each scenario tagged with "#tag1" in your example, you should mark the After hook with "#tag1". For more information on tagged hooks, please refer to the Cucumber documentation.

cleanup after execution of all tests ( spock framework )

i'm looking for a solution that allow me to handle the setup and the cleanup of my test environment at the launch and the end of my test framework execution.
The setup is not a problem but the cleanup imply to know when the test framework has finished to work or the index of the current test in execution queue.
Has someone a solution to implement this?
You can use org.spockframework.runtime.extension.IGlobalExtension to achieve this, as Spock extensions have callbacks for both BEFORE all specs start, and AFTER all specs end.
public interface IGlobalExtension {
void start();
void visitSpec(SpecInfo spec);
void stop();
}
So, implement stop() in your case to do whatever you need to do.
Spock finds extensions via Java's ServiceLoader, so make sure to add a META-INF/services file (pre-Java9) or declare it in your module-info.java file (post Java9), as explained here: http://spockframework.org/spock/docs/1.1/extensions.html#_writing_custom_extensions
One solution is to create an abstract class that all your specs extend:
class AbstractSpec extends Specification
then inside AbstractSpec find out the classes that are going to be run(for example if you're using spring framework):
private static final synchronized TEST_CLASSES = new ClassPathScanningCandidateComponentProvider(false).with {
addIncludeFilter(new AssignableTypeFilter(AbstractSpec.class))
findCandidateComponents("com/example/test").findAll { it.beanClassName != AbstractSpec.class.canonicalName }
.collect { Class.forName(it.beanClassName) }
}
then inside AbstractSpec do the actual clean up after all classes are run:
def synchronized cleanupSpec() {
TEST_CLASSES.remove(getClass())
if (TEST_CLASSES.isEmpty()) {
// clean up here
}
}
The problem with this solution is that if you run a subset of tests or classes in your IDE; you might have all the test classes in the classpath so TEST_CLASSES won't be emptied so the clean up won't execute.

what i the meaning of ApplicationTestCase<Application>

i have been checking code, and i found the following
public class ApplicationTest extends ApplicationTestCase<Application> {
public ApplicationTest() {
super(Application.class);
}
}
can you please explain the meaning of ApplicationTestCase<Application>
It is one type of unit testing of your application. You can test your application automatically base on test cases. No need to test whole application step by step manually.
More info : https://developer.android.com/training/activity-testing/activity-basic-testing.html

How do I re-use (include) Junit test block in other tests

I am fairly new to the JAVA world - coming from a ColdFusion background - and have been learning Java because I'm learning Selenium WebDriver /JUnit. I have written several test classes that test admin functionality that follow a similar structure.
public class myclass{
public static WebDriver driver;
#BeforeClass
public static void startDriver(){
driver = new FirefoxDriver();
driver.get("some url");
}
#Test
public void myLogin(){
some login code
}
#Test
public void somefunction() {
other admin function to test
}
My question is this - since all my tests require the user to log in - I end up having to re-use the "mylogin" test code over and over. How can I write the tests to simply "include" (like the "cfinclude" tag in ColdFusion) the login code so that if changes are made to the login page functionality - I only have to change it in one place.
Java hasn't got a lexical include statement like ColdFusion or C. This is by design, because just pasting sourcecode before compilation is a very unclean way of sharing code between modules.
But there are many other ways to approach this issue. Here are two:
Create your own library with commonly used functionality encapsulated in methods and use this library in your tests
Add setUp and tearDown methods for your test classes. These methods are executed before and after each one of your test methods. Note that test classes can inherit from each other. So when you have lots of test classes with identical setUp and tearDown methods, you can make them extend a common base class and implement these methods in the base class once.
You can implement the myLogin() functionality in a base parent class what you will need to extend in all of your test classes to access this functionality across various tests:
public abstract class MyBaseTest {
public void myLogin() {
<some login code>
}
}
public class MyClass extends MyBaseTest {
#Test
public void somefunction() {
super.myLogin();
}
}
You could use the #Before annotation to accomplish this. The annotated method will run before every #Test annotated method. Similarly you could use #After to logout after every unit test, if needed.

Categories