Cucumber not able to read the definition file - java

I am a beginner in Cucumber and i have written a basic tests for login and going to the homepage using in a maven project. I suspect there is some consistency issue with POM.xml.
Please find below the files
I have tried with multiple combinations for the dependencies in pom file but seems the issue persists.
1) stepdefination file
package StepDefinition;
import org.junit.Assert;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
public class loginStepDefinition {
WebDriver driver;
#Given("^User is already on login page$")
public void user_already_on_login_page(){
System.setProperty("webdriver.chrome.driver","/Users/nilesh.gupta/Desktop/chromedriver" );
driver = new ChromeDriver();
driver.get("https://classic.crmpro.com");
}
#When("^Tittle of login page is Free CRM$")
public void tittle_login_page_is_Free_CRM() {
String tittle = driver.getTitle();
System.out.println("tittle is : " + tittle);
Assert.assertEquals("#1 Free CRM for Any Business: Online Customer Relationship Software", tittle);
}
#Then("^User enters username and password$")
public void user_enters_username_and_password() {
driver.findElement(By.xpath("/html/body/div[2]/div/div[3]/form/div/input[1]\n" )).sendKeys("naveenk");
driver.findElement(By.xpath("/html/body/div[2]/div/div[3]/form/div/input[2]\n" )).sendKeys("test#123");
}
#Then("^User clicks on login button$")
public void user_clicks_on_login_button() {
driver.findElement(By.className("btn btn-small")).click();
}
#Then("^User is on Home Page$")
public void user_is_on_Home_Page() {
String tittle= driver.getTitle();
System.out.println("tittle is : " + tittle );
Assert.assertEquals("CRMPRO", tittle);
}
}
login.feature
Feature: Free CRM Login Feature
Scenario: Free CRM Login Test Scenario
Given User is already on login page
When Tittle of login page is Free CRM
Then User enters username and password
Then User clicks on login button
Then User is on Home Page
testrunner.java
package MyRunner;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "/Users/nilesh.gupta/eclipse-workspace/CucumberBDD/src/main/java/Features/login.feature",
glue={"stepDefinition"}
/*format={"pretty","html:test-output"}*/
)
public class testRunner {
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>CucumberBDD</groupId>
<artifactId>CucumberBDD</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>CucumberBDD</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<cucumber.version>4.8.0</cucumber.version>
<selenium.version>3.5.3</selenium.version>
</properties>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${cucumber.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>${selenium.version}</version>
</dependency>
</dependencies>
</project>
Output
There were undefined steps. You can implement missing steps with the snippets below:
#Given("User is already on login page")
public void user_is_already_on_login_page() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#When("Tittle of login page is Free CRM")
public void tittle_of_login_page_is_Free_CRM() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("User enters username and password")
public void user_enters_username_and_password() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("User clicks on login button")
public void user_clicks_on_login_button() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}
#Then("User is on Home Page")
public void user_is_on_Home_Page() {
// Write code here that turns the phrase above into concrete actions
throw new cucumber.api.PendingException();
}

Please try to make habit to write testing code in the test folder src/test/java instead of main . Everything that write into src/main/java is per default packaged and deliver to your customer whereas everything that you put into src/test/java is no.
Features Options helps Cucumber to locate the Feature file in the project folder structure.
if the Feature file is in the deep folder structure then please use features = “src/test/features“.
Glue
use to locate the Step Definition file.
Once you make changes then please refer below code for your runner file.
package MyRunner;
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/test/features"
,glue={"src/test/stepDefinition"}
,monochrome = false
)
public class testRunner {
}

Try, replace your code in Runner with this. Rebuild project and close and reopen it.
package MyRunner;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/main/java/Features/login.feature",
glue={"StepDefinition"}
/*format={"pretty","html:test-output"}*/
)
public class testRunner {
}

In your example, I think the actual problem is that you cannot use anchors ^ or $ in your stepdefinitions' (Cucumber Expressions) and it shouldn't be there for newer version of io.cucumber. That style is used for info.cukes version.
It should be
#Given("User is already on login page")
public void user_already_on_login_page(){
System.setProperty("webdriver.chrome.driver","/Users/nilesh.gupta/Desktop/chromedriver" );
driver = new ChromeDriver();
driver.get("https://classic.crmpro.com");
}
Instead of
#Given("^User is already on login page$")
public void user_already_on_login_page(){
System.setProperty("webdriver.chrome.driver","/Users/nilesh.gupta/Desktop/chromedriver" );
driver = new ChromeDriver();
driver.get("https://classic.crmpro.com");
}

Related

io.cucumber.junit.UndefinedStepException: The step ''.... are undefined

Been trying to learn/perform some automated testing using Selenium + JUnit + Cucumber and I've spent hours browsing through the internet trying to resolve this with no success. I've written my feature, steps and runner code and the 'glue' is mapped to the correct package too. However, I run into the topic error when I try to run my Runner.java file.
Project Structure
Feature file:
Feature: Admin login
Scenario: Logging into Fleet Portal
Given user navigates to Fleet Portal
When enter credentials
Then user had logged
Runner file:
package Runner;
import org.junit.runner.RunWith;
import io.cucumber.junit.*;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "Features"
,glue="Steps"
)
public class TestRunner {}
Step file:
package Steps;
import java.util.ArrayList;
import java.util.Scanner;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import io.cucumber.java.en.Given;
import io.cucumber.java.en.Then;
import io.cucumber.java.en.When;
class App {
private static final WebDriver driver = new ChromeDriver();
public void myMethod(String flag) {
System.out.println(flag);
}
#Given("user navigates to Fleet Portal")
public void user_navigates_to_fleet_portal() {
throw new io.cucumber.java.PendingException();
}
#When("enter credentials")
public void enter_credentials() throws InterruptedException {
throw new io.cucumber.java.PendingException();
}
#Then("user had logged in successfully")
public void user_had_logged_in_successfully() {
myMethod("yes");
throw new io.cucumber.java.PendingException();
}
}
I've tried to take JUnit out of the picture by simply running the feature file as a cucumber test but it still results in the same error, which is weird because the cucumber plugin confirms that the steps are mapped to the features -> feature mapping
POM file
Any and all help is appreciated.

Java: #AfterStep, #BeforeStep do not work in cucumber

In my Java and maven project I have used cucumber for BDD test.
Here is the dependency I use:
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>4.2.0</version>
</dependency>
my Hooks class:
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.AfterStep;
import cucumber.api.java.BeforeStep;
public class Hooks {
#Before
public void init() {
System.out.println( " Before Scenario " );
}
#After
public void cleanUp() {
System.out.println( " After Scenario " );
}
#BeforeStep
public void beforeStep() {
System.out.println("======> This is before step <======");
//Do something before executing the step
}
#AfterStep
public void afterStep() {
System.out.println("======> This is after step <======");
}
}
But when I run my cucumber test it just prints Before Scenario, and After Scenario. Meanwhile, I expect to see, This is before step, and This is after step
before, and after each step.
So, why #AfterStep, and #BeforeStep do not work?
you should provide a small example which others can use to reproduce your problem
Have a look at this small snippet which is working
Assume the following structure
pom.xml
src/test/java/TestRunner.java
src/test/java/stepdefs/StepDefinitions.java
src/test/java/stepdefs/Hooks.java
src/test/resource/features/demo.feature
pom.xml
...
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<version.cucumber>4.2.0</version.cucumber>
</properties>
<dependencies>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-java</artifactId>
<version>${version.cucumber}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-junit</artifactId>
<version>${version.cucumber}</version>
<scope>test</scope>
</dependency>
</dependencies>
...
TestRunner.java
import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
#RunWith(Cucumber.class)
#CucumberOptions(
features = {"src/test/resource/features"},
glue = {"stepdefs"}
)
public class TestRunner {
}
StepDefinitions.java
package stepdefs;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
public class StepDefinitions {
#Given("^a successful step$")
public void aSuccessfulStep() {
System.out.println(" aSuccessfulStep()");
}
#When("doing something")
public void doingSomething() {
System.out.println(" doingSomething()");
}
#Then("something happen")
public void somethingHappen() {
System.out.println(" somethingHappen()");
}
}
Hooks.java
package stepdefs;
import cucumber.api.java.After;
import cucumber.api.java.AfterStep;
import cucumber.api.java.Before;
import cucumber.api.java.BeforeStep;
public class Hooks {
#Before
public void init() {
System.out.println("#Before scenario");
}
#After
public void cleanUp() {
System.out.println("#After scenario");
}
#BeforeStep
public void beforeStep() {
System.out.println(" #BeforeStep");
}
#AfterStep
public void afterStep() {
System.out.println(" #AfterStep");
}
}
demo.feature
Feature: Test cucumber reporting plugin
Scenario: Run a non failing scenario
Given a successful step
When doing something
Then something happen
running the tests
$ mvn clean test
produces following output
-------------------------------------------------------
T E S T S
-------------------------------------------------------
Running TestRunner
#Before scenario
#BeforeStep
aSuccessfulStep()
#AfterStep
#BeforeStep
doingSomething()
#AfterStep
#BeforeStep
somethingHappen()
#AfterStep
#After scenario
1 Scenarios (1 passed)
3 Steps (3 passed)

How would this testcase ( written in Java using Selenium WebDriver ) look like if the Conductor framework was used?

The following MWE ( described in "Selenium Testing Tools Cookbook, 2nd ed." by Unmesh Gundecha published by Packt publishers ) is a website test using the Selenium Test Framework.
package locators;
import java.util.List;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.WebElement;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
public class TableExample {
protected WebDriver driver;
#Before
public void setUp() {
driver = new ChromeDriver();
driver.get("http://dl.dropbox.com/u/55228056/Locators.html");
}
#Test
public void testWebTable() {
WebElement simpleTable = driver.findElement(By.id("items"));
//Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
assertEquals(3, rows.size());
//Print data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
System.out.print(col.getText() + "\t");
}
System.out.println();
}
}
#After
public void tearDown() {
driver.close();
}
}
Use the following Maven pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>getting-started-with-selenium</groupId>
<artifactId>getting-started-with-selenium</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>getting-started-with-selenium</name>
<description>A quick and easy start-up browser automation framework using Selenium</description>
<properties>
<selenium_version>2.43.1</selenium_version>
</properties>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/main/java</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>io.ddavison</groupId>
<artifactId>conductor</artifactId>
<version>[1,)</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.1</version>
</dependency>
</dependencies>
</project>
Conductor Framework is a framework built on Selenium which promises to minimize Selenium coding in Java.
AFAIK there is no documentation for Conductor except the page at at https://github.com/conductor-framework/conductor.
How would the testWebTable in the TableExample class ( see test above ) look like if the Conductor framework was used? - Is there more documentation on Conductor, in whatever form?
Through trial and error I found that using the Conductor framework the following class works as expected.
import io.ddavison.conductor.Browser;
import io.ddavison.conductor.Config;
import io.ddavison.conductor.Locomotive;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import java.util.List;
import static org.junit.Assert.assertEquals;
// nilostep
#Config(
url = "http://dl.dropbox.com/u/55228056/Locators.html", // base url that the test launches against
browser = Browser.CHROME, // the browser to use.
hub = "" // you can specify a hub hostname / ip here.
)
public class TableExample2 extends Locomotive {
#Test
public void testWebTable2() {
WebElement simpleTable = waitForElement(By.id("items"));
//Get all rows
List<WebElement> rows = simpleTable.findElements(By.tagName("tr"));
assertEquals(3, rows.size());
//Print data from each row
for (WebElement row : rows) {
List<WebElement> cols = row.findElements(By.tagName("td"));
for (WebElement col : cols) {
System.out.print(col.getText() + "\t");
}
System.out.println();
}
}
}

Jsoup returning &nbsp for active text fields

So it seems simple but I can't retrieve the text on this web page, and it seems to be changing.
package WorldBoss;
import org.jsoup.nodes.Document;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.net.MalformedURLException;
public class WorldBoss {
public static void main(String [] args) throws MalformedURLException {
Document page = null;
try {
page = Jsoup.connect("http://wiki.guildwars2.com/wiki/World_boss").get();
} catch (IOException e) {
e.printStackTrace();
}
Elements allTimers = page.getElementsByClass("timerjs");
String firstTime = allTimers.first().html();
System.out.println(firstTime);
}
}
It is changing due to it being a countdown.
In the properties on the page it says the innerHTML is correct
Does anyone know how I can get this information with Jsoup?
The page is here if you want to check it out.
As Pshemo mentioned in the comment, Jsoup is an html parser so it neither renders the page nor executes the scripts on it.
To successfully extract the fields you desire, I have made slight modifications to your code by using the phantomjs driver through selenium. The page is fetched and rendered using phantom and the page source is piped to Jsoup for parsing. Find the code below:
import org.jsoup.nodes.Document;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.phantomjs.PhantomJSDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
public class WorldBoss {
public static void main(String [] args) {
WebDriver driver = new PhantomJSDriver(new DesiredCapabilities());
driver.get("http://wiki.guildwars2.com/wiki/World_boss"); //retrieve page
//It is very bad to wait explicitly, the best practice is to wait for a specific element on the page e.g. the element you're looking for [1]
try { // wait to ensure page is loaded and java script is rendered
Thread.sleep(3 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String pageSource = driver.getPageSource();
Document page = Jsoup.parse(pageSource);
Elements allTimers = page.getElementsByClass("timerjs");
for (Element timer : allTimers) {
//you can get whichever timer you want with it's index
String firstTime = timer.html().trim();
if (firstTime.isEmpty()) continue;
//use timer for whatever you want
System.out.println(firstTime);
}
}
}
I used maven so the dependencies in the pom file are:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.7.2</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.47.1</version>
</dependency>
<dependency>
<groupId>com.github.detro.ghostdriver</groupId>
<artifactId>phantomjsdriver</artifactId>
<version>1.0.1</version>
</dependency>
The code output is:
Active
00:01:33
00:01:33
00:16:33
00:31:33
00:46:33
If you don't have phantomjs installed on your machine, you need to install it for this to work. To install phantom on a debian based box:
sudo apt-get install phantomjs
For other platforms (or to build from source) see how to install phantom.
Hope this helps.
How to wait for elements in selenium

Jersey client side strategy to test main page after login

I am using Jersey to create a web application. Currently there are two pages: login and main page. When user inputs correct username and password, the login page gets redirected into main page (otherwise the warning is presented in a pop up window, with no redirection).
In the main page, certain content is retrieved from the server and updated on the page.
Since there is no of username and password on the main page, how can I write client side code to varify whether the correct content is rendered to the main page, after the user is logged in successfully?
One way is to use an HTML parsing library, like jsoup. Here's a complete example, using Jersey Test Framework. You can run it just like any other unit test
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.test.JerseyTest;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.junit.Test;
import static junit.framework.Assert.*;
public class HtmlParserTest extends JerseyTest {
#Path("login")
public static class LoginController {
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.TEXT_HTML)
public String doLogin(MultivaluedMap<String, String> formParams) {
boolean valid = false;
valid = "user".equals(formParams.getFirst("username"));
valid = "pass".equals(formParams.getFirst("password"));
String message = valid ? "You Win!" : "You Lose!";
String html
= "<html>\n"
+ " <body>\n"
+ " <h1 id=\"message\">" + message + "</h1>\n"
+ " </bod;y>\n"
+ "</html>";
return html;
}
}
#Override
public Application configure() {
return new ResourceConfig(LoginController.class);
}
#Test
public void youWinMessageWithValidCredentials() {
String message = handleRequest("pass");
assertEquals("You Win!", message);
}
#Test
public void youLoseMessageWithBadCredentials() {
String message = handleRequest("wrong");
assertEquals("You Lose!", message);
}
private String handleRequest(String password) {
Form form = new Form();
form.param("username", "user");
form.param("password", password);
String html = target("login").request()
.accept(MediaType.TEXT_HTML)
.post(Entity.form(form), String.class);
return getMessageContent(html);
}
/* jsoup code */
private String getMessageContent(String html) {
Document document = Jsoup.parse(html);
Element messageElem = document.getElementById("message");
return messageElem.text();
}
}
Here are the dependencies for the test
<dependency>
<groupId>org.glassfish.jersey.test-framework.providers</groupId>
<artifactId>jersey-test-framework-provider-grizzly2</artifactId>
<scope>${jersey2.version}</scope>
</dependency>
<dependency>
<!-- jsoup HTML parser library # http://jsoup.org/ -->
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.2</version>
<scope>test</scope>
</dependency>
You could use the Arquillian Framework for such kind of tests. Besides the Arquillian Core lot's of extensions are available.
For your use case I would use the Arquillian Drone Extension and the REST Extension (if you are using restful services after the login).
Arquillian Drone allows you to write client side tests for web sites and with the rest extension restful webservices can be tested.
Here is an example for testing a login page with Arquillian Drone.

Categories

Resources