Cucumber Runner Class not running Step Definitons - java

I am writing automated tests with Cucumber and Java.
I can run the step definitions by right-clicking on my Feature file, and running it as a Cucumber Feature, and all steps pass successfully.
But, I need to run them using a Runner Class.
My feature file is in this folder:
src/test/java/features
And my step definitons are in this folder:
src\test\java\com\abc\commercial\def\automation
My Runner Class is also stored in
src\test\java\com\abc\commercial\def\automation
And here is the Runner Class code:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"progress",
"html:build/report/html",
"junit:build/report/junit/cucumber-report.xml",
"json:build/report/json/cucumber-report.json"
},
glue = {"src\\test\\java\\com\\abc\\commercial\\def\\automation"},
features = {"src/test/java/features"}
)
public class QARunner {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
When I run the Runner Class as a JUnit Test, I receive the following response in the console:
UUUUUUUUU
Undefined scenarios:
src/test/java/features/US46052
src/test/java/features/postFeatures.feature:43 # As the
2 Scenarios (2 undefined)
9 Steps (9 undefined)
0m0.303s
You can implement missing steps with the snippets below:
#Given("the Application...")
public void the_Application...() {
So the step definitions are not being picked up.
Does it have something to do with where my test runner is located?
I don't think it is picking up the step definitons in the automation folder
Thanks for any help

Try this : No need for main method. glue option should be in package style.
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"progress",
"html:build/report/html",
"junit:build/report/junit/cucumber-report.xml",
"json:build/report/json/cucumber-report.json"
},
glue = {"com.abc.commercial.def.automation"},
features = {"src/test/java/features"}
)
public class QARunner {
}

Related

Cucumber hooks are not running. I am using io.cucumber.java8

I am trying to run steps required before and after the scenarios using Cucumber hooks, but the methods in hooks class are not running. Below is the hooks class.
Used dependencies :
<cucumber.version>6.11.0</cucumber.version>
package com.neobank.hooks;
import com.neobank.core.Driver;
import io.cucumber.java8.En;
public class ScenarioHooks implements En {
public ScenarioHooks() {
Before(Driver::startAppiumDriver);
After(Driver::resetApp);
After(Driver::stopChromeDriver);
}
}
Glue Path:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {"pretty", "html:target/cucumber.html",
"json:target/cucumber.json"},
features = {"src/test/resources/features"},
glue = {"com.neobank.steps", "com.neobank.hooks"},
tags = "#Onboardingtwo"
Found out the issue here. Was trying to run the cucumber scenarios individually from feature files. If hooks are to be executed then we have to run using the runner file.

Using JUnit Hooks with Cucumber CLI Runner

I'm trying to run Cucumber's feature files in parallel using Cucumber's CLI Runner and I'm currently stuck trying to figure out how to make JUnit #BeforeClass hook to work with the CLI Runner.
At the moment, my working Runner class looks like this:
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {
"pretty",
"html:target/reports/basic/report.html",
"json:target/reports/cluecumber/cucumber.json",
"timeline:target/reports/timeline"
},
tags = "#RegressionTests",
snippets = SnippetType.CAMELCASE,
stepNotifications = true,
features = "classpath:features",
glue = "my.steps.package")
public class RegressionTestsIT {
#BeforeClass
public static void setup() {
ContextHolder.setupTestContext();
}
}
And my CLI command looks like this:
java -cp "target/test-jar-with-dependencies.jar" io.cucumber.core.cli.Main -p "pretty" -p "html:target/reports/basic/report.html" -p "json:target/reports/cluecumber/cucumber.json" -p "timeline:target/reports/timeline" --threads 10 -g "my.steps.package" target/test-classes/features
What happens is that I get a NullPointerException at the tests because TestContext was not properly set up as the hook was not executed.
I tried to include both the Runner's package and the Runner class itself as glue and it didn't work.
Also tried to make my Runner extend io.cucumber.core.cli.Main and then execute my Runner in the CLI and not surprisingly it did not work either, sadly still getting NPE.
Although this issue is related to the CLI Runner use, I'm content with any answer that might help me run multiple feature files in parallel whatever the method.
Using JUnit Rules
Cucumber supports JUnit's #ClassRule, #BeforeClass, and #AfterClass annotations. These will be executed before and after all scenarios. Using these is not recommended as it limits portability between different runners; they may not execute correctly when using the command line, IntelliJ IDEA, or Cucumber-Eclipse. Instead it is recommended to use Cucumber's hooks.
When using the CLI, JUnit is not involved at all so you can not use any of JUnit annotations. However since Cucumber v7 you can use #BeforeAll and #AfterAll to declare methods that executed before and after all scenarios.
package io.cucumber.example;
import io.cucumber.java.AfterAll;
import io.cucumber.java.BeforeAll;
public class StepDefinitions {
#BeforeAll
public static void beforeAll() {
// Runs before all scenarios
}
#AfterAll
public static void afterAll() {
// Runs after all scenarios
}
}
JUnit #BeforeClass didn't work for me. Since I'm kinda in a hurry with this, I didn't bother keep on trying to make it work. I don't really need to run the command in a pipeline at the moment, so I was completely fine in running it on IntelliJ as long as it was running in parallel.
My solution was creating a custom CLI Runner that runs the context configuration before Cucumber's CLI run method.
public class CLIRunner {
public static void main(String[] args) {
ContextHolder.setupTestContext();
io.cucumber.core.cli.Main.run(
new String[] {
"-p", "pretty",
"-p", "html:target/reports/basic/report.html",
"-p", "json:target/reports/cluecumber/cucumber.json",
"-p", "timeline:target/reports/timeline",
"-g", "my.steps.package",
"classpath:features",
"--threads", "10"
}, Thread.currentThread().getContextClassLoader());
}
}

Cucumber exception when run the test

I have a problem that I think is silly ...
I can't run my tests on the cucumber.
Returns the following error:
cucumber.runtime.CucumberException:
Classes annotated with #RunWith(Cucumber.class) must not define any
Step Definition or Hook methods. Their sole purpose is to serve as
an entry point for JUnit. Step Definitions and Hooks should be defined
in their own classes. This allows them to be reused across features.
Offending class: class Teste.testecucumber
Could anyone help?
Thank you !!
#Runwith is declared in the TestRunner class of a Cucumber project. The Cucumber project has 3 defined types of classes:
Step Definition class
Feature class
Runner class
Please find the below examples for the above classes:
1. Feature Class
The test cases are written in this class
Feature: Title of your feature
I want to use this template for my feature file
#tag1
Scenario: Verify login to the system.
Given I navigate to url
And I enter username as "username"
And I enter password as "password"
When I click Login
Then I should be logged into the system
2. Step Definition class
The feature steps are defined in this class
public class LoginPage(){
#Given("I navigate to the url")
public void navigate() {
/* your code for the above
step comes here*/
}
}
3. Runner Class
The runner class consist of the location of features and step definition. It is a Junit class and cannot contain cucumber step definition annotations. (This is the reason why runner class cannot be a step definition class). But, you can include the BeforeClass, AfterClass (Junit annotations) in this class
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"classpath:<location of your folder with feature classes / package name>"},
glue = {"<package name>" },
tags = { "<the tags that has to be executed>","can be comma separated multiple tags" }
)
public class testrunner {
//#AfterClass
public static void quitDriver() {
driver.quit();
}
}
Hope this helps you !

Running Cucumber and Spring boot in Main class

My requirement is to run Cucumber test cases using Spring boot to run through a Custom java main class.
I am able to run Cucumber test suite fine if i am using following config class:-
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = {
"html:target/cucumber-html-report",
"json:target/cucumber.json", "pretty:target/cucumber-
pretty.txt",
"usage:target/cucumber-usage.json", "junit:target/cucumber-
results.xml" },
features = { "src/test/resources" },
tags = {"#passed"},
glue = "cucumberTest.steps")
public class RunGwMLCompareTests {
}
And following class to load
#RunWith(SpringRunner.class)
#ActiveProfiles("dev")
#SpringBootTest(classes = Application.class)
public class AbstractDefinitions {
public AbstractDefinitions() {
}
}
And when i run RunGwMLCompareTests class,Now using this config my Cucumber test cases are running , It loads my Spring boot context and then exceutes all cases defined in feature.
Now my issue is that i want to run this from seperate main java class. I have created my java class as follows :-
package cucumberTest;
import cucumber.runtime.ClassFinder;
import cucumber.runtime.RuntimeOptions;
import cucumber.runtime.io.MultiLoader;
import cucumber.runtime.io.ResourceLoader;
import cucumber.runtime.io.ResourceLoaderClassFinder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class CucumberMainTest {
public static void main(String[] args) throws IOException {
ClassLoader classLoader = CucumberMainTest.class.getClassLoader();
ResourceLoader resourceLoader = new MultiLoader(classLoader);
ClassFinder classFinder = new
ResourceLoaderClassFinder(resourceLoader, classLoader);
List<String> pluginList = new ArrayList<>();
pluginList.add("--plugin");
pluginList.add("html:target/cucumber-html-report");
pluginList.add("--plugin");
pluginList.add("json:target/cucumber.json");
RuntimeOptions ro = new RuntimeOptions(pluginList);
ro.getFilters().add("#passed");
ro.getFeaturePaths().add("src/test/resources");
ro.getGlue().add("cucumberTest/steps");
cucumber.runtime.Runtime runtime = new
cucumber.runtime.Runtime(resourceLoader, classFinder, classLoader,
ro);
runtime.run();
}
}
It executes my test cases but does not load my SpringContext, as a result no spring beans are loadedand i get null pointer exception.. Any help is geatly appreciated.
Regards,
Vikram Pathania
One solution i found was to run RunGwMLCompareTests class from outside which handles my Spring context automatically.
So basically i am using gradle to create batch file which does nothing but automatically creates a batch with all relative depencies in my class path and then run following command:
"%JAVA_EXE%" -classpath "%CLASSPATH%" org.junit.runner.JUnitCore
cucumberTest.runners.RunGwMLCompareTests
where,
JAVA_EXE=C:\Program Files\Java\jdk1.7.0_65/bin/java.exe
And CLASSPATH is lib folder where all jars are present.
CLASSPATH=%APP_HOME%\lib\*.jar
Now running this batch i am using
features = { "src/test/resources" } <tag>
to put my feature files outside so that it can edited on the fly.
I hope this helps somebody out there.
by doing this , i am able to run RunGwMLCompareTests class.
Now using this config my Cucumber test cases are running and It also loads my Spring boot context and then exceutes all cases defined in feature.
Regards,
Vikram Pathania

How to link feature and step definition in cucumber

I'm new to Cucumber java and had this problem in initial stages:
I'm not using MAVEN project for some reason. I just created a simple java project in eclipse.
I have my features under "src/dummy/pkg/features", and my implementation "StepDef.java" is under "src/dummy/pkg/features/implementation"
I have written step definitions for Given, When, and Then, but when I run my features file, it is unable to recognize the implementation. How do I link the features with step definitions?
create a class YourClass and it would look something like the below and run it as JUnit test.
#RunWith(Cucumber.class)
#CucumberOptions( monochrome = true,
features = "src/dummy/pkg/features/",
format = { "pretty","html: cucumber-html-reports",
"json: cucumber-html-reports/cucumber.json" },
glue = "your_step_definition_location_package" )
public class YourClass {
//Run this from Maven or as JUnit
}
When you run your Runner class then it will scan all the feature file mentioned within features options and load the them afterward all step definition within package started by text mentioned within glue options will get loaded.
For e.g.
#RunWith(Cucumber.class)
#CucumberOptions(
plugin = { "pretty","json:target/cucumberreports.json" },
glue = "stepDefinition",
features = "src/test/resources/TestCases/",
tags={"#onlythis"},
dryRun=false
)
public class RunTest {
}
Here all the feature file present within
src/test/resources/TestCases/
will get loaded
then all the stepdef within or it's subdirectory will get loaded
stepDefinition
and whenever your step from feature get run then cucumber will look for function corresponding to step's regex and function will run.
for e.g.
whenever step When User enters email id in src/test/resources/TestCases/Login.feature will run then cucumber will find its corresponding function in all stepdef classes
Login.feature
#LoginValidation
Feature: To smoke test functionalities of app
#Browser #ValidLogin
Scenario: Verify scenario in case of successful login
When User enters email id
And User enters password
Then User clicks on sign in button and able to sign in
And moment it will reach class in subdirectory of stepDefinition i.e. in
stepDefinition.ui.home.LoginPageStepDef.java cucumber will find function with #When("^User enters email id$") and will execute this function.
LoginPageStepDef.java
public class LoginPageStepDef {
LoginPage loginPage = new LoginPage(AttachHooks.driver);
private static Logger LOGGER = Logger.getLogger(LoginPageStepDef.class);
#When("^User enters email id$")
public void user_enters_email_id() throws Throwable {
//LoginPage.obj = loginPage;
loginPage.enterEmailId(ConfigManager.getProperty("UserName"));
}
}
You have to convert your project to Cucumber project. Right-click on your project from the Project Explorer > Configure > Convert as Cucumber Project.
Create a runner class something like this and you should be able to execute.
There is also no need to write step definitions manually, just create a feature file and run it, it will create a snippet of the step definition which can be used to create a step definition class:
A class file called Runnerclass is required to run the cucumber:
#RunWith(Cucumber.class)
#CucumberOptions(plugin={"pretty","html:format"},
features = "Features/name.feature",glue={"path where step definitions exist"})
public class RunnerClass {
}

Categories