I have a Selenium
test based on Cucumber
and Spring Boot
that throws an exception (error shown below) when I tried to simplify the test by moving the methods setup()
and closeBrowser()
in the parent class.
If I cut-paste both these methods in GoogleCalcStepDefinition.java
file everything works fine and the tests also pass without any issues.
Not sure how to move these common methods to another class to simplify the tests and support maintainability and extensibility.
I googled around and found this SO link (Cucumber class extending step definitions and hooks) but it does not have any code snippet and does not provide much help.
Please guide.
DemoApplicationTests.java
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class DemoApplicationTests {
private static final String CHROME_DRIVER_EXE = "drivers/chromedriver.exe";
private static final String WEBDRIVER_CHROME_DRIVER = "webdriver.chrome.driver";
private WebDriver driver;
private GoogleSearchPage googleSearchPage;
@Before //this uses cucumber.api.Before (equivalent of JUnit @BeforeClass)
public void setup() {
String filePath = ClassLoader.getSystemClassLoader().getResource(CHROME_DRIVER_EXE).getFile();
System.setProperty(WEBDRIVER_CHROME_DRIVER, filePath);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("useAutomationExtension", false);
driver = new ChromeDriver(options);
googleSearchPage = PageFactory.initElements(driver, GoogleSearchPage.class);
}
@After //this uses cucumber.api.After (equivalent of JUnit @AfterClass)
public void closeBrowser() {
if (null != driver) {
driver.close();
driver.quit();
}
}
}
GoogleCalcStepDefinition.java
@Ignore
public class GoogleCalcStepDefinition extends DemoApplicationTests {
@Given("^I open Google$")
public void I_open_google() {
//Set implicit wait of 5 seconds and launch google
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
driver.get("https://www.google.co.in");
}
@When("^I enter \"([^\"]*)\" in search textbox$")
public void I_enter_in_search_textbox(String additionTerms) {
googleSearchPage.searchBox.sendKeys(additionTerms); //passing 2+2 here
googleSearchPage.searchBtn.click();
}
@Then("^I should get result as \"([^\"]*)\"$")
public void I_should_get_correct_result(String expectedResult) {
String result = googleSearchPage.calculatorTextBox.getText();
assertEquals(result, expectedResult); //Verify that result of 2+2 is 4
}
}
TestRunner.java
@RunWith(Cucumber.class)
@CucumberOptions(
plugin = {"pretty", "json:target/cucumber-reports/cucumber.json"},
features = {"src/test/resources/features"})
public class TestRunner {
}
GoogleSearchPage.java
public class GoogleSearchPage {
@FindBy(name = "q")
WebElement searchBox;
@FindBy(name = "btnK")
WebElement searchBtn;
@FindBy(id = "cwos")
WebElement calculatorTextBox;
}
calc.feature (src/test/resources/features)
Feature: Check addition in Google calculatorcontent
In order to verify that Google calculator work correctly
As a user of Google
I should be able to get correct addition result
Scenario: Addition
Given I open Google
When I enter "2+2" in search textbox
Then I should get result as "4"
pom.xml
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-spring</artifactId>
<version>4.2.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-chrome-driver</artifactId>
<version>2.45.0</version>
<scope>test</scope>
</dependency>
Error (when I execute TestRunner):
cucumber.runtime.CucumberException: You're not allowed to extend classes that define Step Definitions or hooks. class com.example.GoogleCalcStepDefinition extends class com.example.DemoApplicationTests
at cucumber.runtime.java.MethodScanner.validateMethod(MethodScanner.java:76)
at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:62)
at cucumber.runtime.java.MethodScanner.scan(MethodScanner.java:43)
at cucumber.runtime.java.JavaBackend.loadGlue(JavaBackend.java:83)
at cucumber.runner.Runner.<init>(Runner.java:28)
at cucumber.runner.ThreadLocalRunnerSupplier.createRunner(ThreadLocalRunnerSupplier.java:42)
at cucumber.runner.ThreadLocalRunnerSupplier.access$000(ThreadLocalRunnerSupplier.java:13)
at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:22)
at cucumber.runner.ThreadLocalRunnerSupplier$1.initialValue(ThreadLocalRunnerSupplier.java:19)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:180)
at java.lang.ThreadLocal.get(ThreadLocal.java:170)
at cucumber.runner.ThreadLocalRunnerSupplier.get(ThreadLocalRunnerSupplier.java:38)
at cucumber.api.junit.Cucumber.<init>(Cucumber.java:106)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:49)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Process finished with exit code -1