Cucumber- // Write code here that turns the phrase above into concrete actions - selenium

I Tried to execute the same test with different data but I am getting the following error when I tried to run the test
You can implement missing steps with the snippets below:
#When("^Enter the ADMIN and password(\\d+)$")
public void enter_the_ADMIN_and_password(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
Below is my Feature file
Scenario Outline: Login
Given Open chrome and login
When Enter the <Username> and <Password>
Then Click on Login
Examples:
|Username |Password |
|ADMIN |password123|
Below is the #when annotation part in Steps file
#When("^Enter the \"(.*)\" and \"(.*)\"$")
public void enter_the_Username_and_Password(String username,String Password) throws Throwable
{
System.out.println("This step enter the Username and Password on the login page."+username +Password);
loginObj.Login(driver);
}

It may be occurring due to cucumbers packages is misconfigured. Check the GLUE options
#RunWith(Cucumber.class)
#CucumberOptions(
features = { "src/test/resources/features/CucumberTests.feature" },
tags = { "#integration_test"},
glue = { "br.com.cucumber.integration.stepDefinition" },
format = { "pretty", "html:target/reports/cucumber/html", "json:target/cucumber.json", "usage:target/usage.jsonx", "junit:target/junit.xml" })
#ContextConfiguration(classes= AppConfiguration.class)
public class CumcumberTest extends BaseTestCase {
}

I think what you are describing as an "error" is in fact cucumber telling you that is not able to find the matching definition for the step "When Enter the Username and Password" and has auto-generated the example definition below based on the scenario outline data:
#When("^Enter the ADMIN and password(\\d+)$")
public void enter_the_ADMIN_and_password(int arg1) throws Throwable {
// Write code here that turns the phrase above into concrete actions
throw new PendingException();
}
The problem is that your step definition is using quotes on the parameters but your actual step has no quotes, hence cucumber is not able to match them. You either need to change your step in the feature file to include quotes:
When Enter the "<Username>" and "<Password>"
Or you need to change the step definition to not include quotes:
#When("^Enter the (.*) and (.*)$")
public void enter_the_Username_and_Password(String username,String Password) throws Throwable
{
System.out.println("This step enter the Username and Password on the login page."+username +Password);
loginObj.Login(driver);
}

I got the same error. For me the problem was that I created step definition in the package for back end tests instead of front end ones. If the step definition classes have same or similar names, it is possible to make a mistake. This would happen during chosing the wrong package while creating step definition from the feature file in Intellij.

I was getting this issue and discovered the reason was I accidentally gave the name of the class and not the package for the glue code:
The wrong argument value for my gluecode was my class as: gluecode="StepDefinition", when it should have been my package: gluecode="stepDefs"
My TestRunner.java looks as follows:
package testRunner;
import org.junit.runner.RunWith;
import io.cucumber.junit.Cucumber;
import io.cucumber.junit.CucumberOptions;
#RunWith(Cucumber.class)
#CucumberOptions(
features = "src/test/java/features",
glue = "stepDefs")
public class TestRunner {
}

I got the same error. In my case I was forgetting the .step. part in my file name.
So I've solved by modifying my file name from:
mystepfile.ts
to:
mystepfile.step.ts

Related

How to manage the step definition code that needs to be reused again & again

My feature file contains a feature that needs to be reused by each and every step definition file again & again. How to manage the code
My feature is :-
"User is on home Page".
The above feature / scenario contains a code that needs to be reused again & again. In my code base , for every feature file i have written separate step definition.
My first step definition file :-
#Given ("^user is on HomePage$")
public void user_homePage()
{
configFileReader =new ConfigFileReader();
System.setProperty("webdriver.chrome.driver","D:\\chromedriver.exe");
driver=new ChromeDriver();
driver.get("https://parabank.parasoft.com/parabank/index.htm");
driver.manage().window().maximize();
}
Now the same feature needs to be used in another step definition file. i.e
here below
Before user clicks on 'Register' link , it should verify that user is on homePage. The description of 'User is on home page' is defined in first step definition file .
Now how to manage the code here :-
My Second Step definition file here below:-
import StepFiles.ParaBank_TC_01_Step; [ I have even imported first step definition file , so that feature "User is on home page" could be executed. ]
public class ParaBank_TC_02_Step {
public WebDriver driver;
ConfigFileReader configFileReader;
#When ("^user clicks on register link$")
public void click_register() throws InterruptedException
{
Thread.sleep(3000);
WebElement register_link= driver.findElement(By.xpath("//a[contains(text(),'Register')]"));
register_link.click();
}
Actual Result :-
1. When i write all the step definition for 2 features files in one file , then it executes perfectly fine , because feature 'User is on home page' is defined in one same file.
As i write separate step definition for feature 2 in another java file. It shows me "Null pointer exception" error because on feature "User is on home page" > driver is initialised in 1 step def file . It isn't executing for second step definition file.
Please help me out in understanding the root cause of this issue & provide the best possible solution.
In order to share state between steps, you can use dependency injection (DI). Cucumber offers support for several DI frameworks. We recommend you use either the one your application already uses / you are familiar with (in my case, that is Spring). Otherwise, we recommend PicoContainer as the most lightweight option.
You can find a little more information about using DI in the Cucumber docs and the related code on GitHub.
For more information on using PicoContainer, see this blogpost.
To use Spring, please have a look at my blogpost.
To use Guice, have a look at this blogpost.
Sidenote:
Feature-coupled step definitions (defining the step definitions for each feature in a separate file, in a way so that they cannot be reused across features), is considered an anti-pattern, as "This may lead to an explosion of step definitions, code duplication, and high maintenance costs."
(from the Cucumber docs).
The solution is to decouple your step definitions:
"
* Organise your steps by domain concept.
Use domain-related names (rather than feature- or scenario-related names) for your step & step definition files."
(from the Cucumber docs).
In order to do so, you will need to use DI.
If you are interested to implement PicoContainer, please follow below steps for good understanding :
Step 1. OrderSelectionStepDef & OrderDetailsStepDef would look like below (please change name as per your implementation)
/**
* Step Definition implementation class for Cucumber Steps defined in Feature file
*/
public class HomePageSteps extends BaseSteps {
TestContext testContext;
public HomePageSteps(TestContext context) {
testContext = context;
}
#When("^User is on Brand Home Page (.+)$")
public void user_is_on_Brand_Home_Page(String siteName) throws InterruptedException {
homePage = new HomePage().launchBrandSite(siteName);
testContext.scenarioContext.setContext(Context.HOMEPAGE, homePage);
}
#Then("^Clicking on Sign In link shall take user to Sign In Page$")
public void clicking_on_Sign_In_link_shall_take_user_to_Sign_In_Page() {
homePage = (HomePage) testContext.scenarioContext.getContext(Context.HOMEPAGE);
signInPage = homePage.ecommSignInPageNavigation();
testContext.scenarioContext.setContext(Context.SIGNINPAGE, signInPage);
}
For your reference
public class BaseSteps {
protected HomePage homePage;
protected PLPPage plpPage;
protected PDPPage pdpPage;
protected ShoppingBagPage shoppingBagPage;
protected ShippingPage shippingPage;
More implementation goes here.....
}
Step 2. Please add below 2 Classes under your framework -
First, Java file name - ScenarioContext.java
public class ScenarioContext {
private Map<String, Object> scenarioContext;
public ScenarioContext(){
scenarioContext = new HashMap<String, Object>();
}
public void setContext(Context key, Object value) {
scenarioContext.put(key.toString(), value);
}
public Object getContext(Context key){
return scenarioContext.get(key.toString());
}
public Boolean isContains(Context key){
return scenarioContext.containsKey(key.toString());
}
}
Second, Java file name - TestContext.java
public class TestContext {
public ScenarioContext scenarioContext;
public TestContext(){
scenarioContext = new ScenarioContext();
}
public ScenarioContext getScenarioContext() {
return scenarioContext;
}
}
Step 3. POM Dependency - picocontainer shall be as per your cucumber version
<dependency>
<groupId>io.cucumber</groupId>
<artifactId>cucumber-picocontainer</artifactId>
<version>${cucumber.version}</version>
</dependency>

Can't run my test JUnit step definition

I want to run test JUnit i work in 2 different projets :
In the first one i have
The feature :
Feature: Google Search
Scenario: Validate google search text field
Given open a browser
When navigate to google page
Then validate search text field
The Step definition Class :
#Given("^open a browser$")
public void open_a_browser() throws Throwable {
System.setProperty("webdriver.chrome.driver", "D:\\Drive\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
}
#When("^navigate to google page$")
public void navigate_to_google_page() throws Throwable {
driver.get("http://www.google.com");
}
#Then("^validate search text field$")
public void validate_search_text_field() throws Throwable {
driver.findElement(By.name("q")).sendKeys("selenium "); }
And the Runner class :
#RunWith(Cucumber.class)
#CucumberOptions(features={"src\\test\\resources\\com\\tutoriel\\testing\\features\\Googlesearch.feature",
glue={"com\\tutoriel\\testing\\stepdefinitions"})
public class RunTestRunner {
}
And it works for me very good
but when i tr to add those 3steps (feature, stepdef and the runner ) in an big another project it doesn't work
i don't undersand the issue !!
this is the error
You can implement missing steps with the snippets below:
but i have already defined them in the class steps definition
Anyone can help me please

Selenium framework and test data in json

I am just completed a test automation using with selenium. And I want to know about how to keep the test data separately in json format.
Can you please tell me how to write test data in the page object pattern.
Here I am using multiple packages. One is for locators identification, another is for page factory for initializing elements, and the other is package utilities for common values like get URL. I also have a test package for testing a login module.
What I don't know is where should I put the test data class ?
I want to keep the test data separately. Not scattering all over the script. Keep the test data in Json. And read it from there where ever it is necessary.
Still I'm getting confusing about where Should I put the json format
And also I am selenium code doesn't follow a framework. I did n't follow any frameworks. Anybody please tell me about frameworks ?
Frameworks are : Data driven, keyword driven, hybrid and modular. which framework is most people using , because and why ?
As a tester should have knowledge about all frameworks ?
I am following page object design pattern:
Page object :
package pageobjects;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.How;
public class HomePage
{
#FindBy(how= How.NAME, using = "username")
WebElement username;
#FindBy(how=How.NAME, using = "password")
WebElement password;
#FindBy(how=How.XPATH, using="//*[#id=\'login-container\']/form/div[3]/div/p/input[1]" )
WebElement button;
//enter username
public void userLogin(String user, String pass)
{
username.sendKeys(user);
password.sendKeys(pass);
button.click();
}
}
Steps:
package steps;
import org.openqa.selenium.support.PageFactory;
import pageobjects.ClientPage;
import pageobjects.HomePage;
import util.DriverManager;
public class LoginSteps
{
public HomePage Login(String nam, String pas) {
HomePage homePageObj = PageFactory.initElements(DriverManager.driver, HomePage.class);
homePageObj.userLogin(nam,pas);
return homePageObj;
}
}
Util:
package util;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
public class DriverManager
{
public static WebDriver driver;
String baseUrl="//http:qms";
public DriverManager()
{
System.setProperty("webdriver.chrome.driver","/home/naveen/chromedriver");
driver=new ChromeDriver();
driver.get(baseUrl);
driver.manage().window().maximize();
}
}
Login Test :
package login;
import org.testng.Assert;
import org.testng.annotations.*;
import pageobjects.HomePage;
import steps.LoginSteps;
import util.DriverManager;
import static util.DriverManager.driver;
public class loginTest
{
#BeforeSuite(groups = {"regression"})
public void initDriver(){
DriverManager manager = new DriverManager();
}
#DataProvider(name= "login")
public static java.lang.Object[][] loginData(){
return new Object[][]{{"geoso","1"},{"ges","2"},{"geo","1"}};
}
#Test(dataProvider = "login")
public void verifyValidLoginWithDataProvider(String userName,String password)
{
LoginSteps loginSteps= new LoginSteps();
HomePage ex=loginSteps.Login(userName,password);
Assert.assertTrue(driver.getPageSource().contains("Hello Naveen"));
}
}
Here is the scenario of json format Please tell me how to write the code?
first open URL and go to login page then .
login
{
"username" :"ertte"
password: "34"
}
"Admin"
"users"
"add users"
"username" :"tsrt"
"password":"sdfgsdrfg"
name:"gfgf"
nickname:"fgsdgf"
role:"client"
email:"sdfsd#gmail.com"
submit
}}
There are so many different frameworks you can use now in combination with selenium.
I use Cucumber [BDD].
You can write your scenarios as regular sentences and Gherkin will transfer them in a methods. Sentences can have parameters or list of a parameters.
You have execution control for your test at two, let call it top levels. You can choose which feature file you want to ran.
Second execution filter can be build by using tags. For e.g. #smoketest #regression and so on.
You can use also TestNG. You have .xml file where you can make your setup. Execute particular clases, methods, prioretize test, make test dependencies, skip tests, and have full control over execution.
There are lot more I assume but these two are the most popular.

Using SpecFlow, Selenium and FluentAutomation causing problems

I am currently using Specflow with Selenium and FluentAutomation, and am running into significant problems with maintaining state between steps in specflow.
See my example code below:
[Binding]
public class RegistrationSteps : FluentTest
{
[Given(#"I create an account")]
public void GivenICreateAnAccount()
{
new HomePage(this)
.Go()
.StartRegistration()
.EnterDetailsAndClickSubmit(); // takes me to deposit page
}
[When(#"Deposit '(.*)' dollars in my account")]
public void GivenDepositMoneyInMyAccount(int amount)
{
new DepositPage(this)
.EnterDetailsAndClickSubmit(amount);
}
}
My problem is:
In the first step the page is loaded using Go() and everything happens fine
In the second step my tests continue, here I expect I am on a different page, based in the Submit in the previous
Because I am no on a different PageObject it gets confused, I don't use Go because the previous step shouldve brought me here, and at this stage it wont find the expected elements
So my question is, how can I use one browser session and several PageObjects across multiple Specflow tests?
According to the FluentAutomation doc, you should do something like this:
[Binding]
public class RegistrationSteps : FluentTest
{
private PageObject _currentPage;
[Given(#"I create an account")]
public void GivenICreateAnAccount()
{
_currentPage = new HomePage(this)
.Go()
.StartRegistration()
.EnterDetailsAndClickSubmit(); // takes me to deposit page
}
[When(#"Deposit '(.*)' dollars in my account")]
public void GivenDepositMoneyInMyAccount(int amount)
{
_currentPage = _currentPage
.EnterDetailsAndClickSubmit(amount);
}
}
Provided that you return the page object that is switched to in the EnterDetailsAndClickSubmit method of your concrete page object like:
Public PageObject EnterDetailsAndClickSubmit() {
// [.. enter details here and click submit ..]
return this.Switch();
}

jbehave run only specific story

I have jbehave integrated with Selenium. I am running my tests through command line as below
C:\eclipse_workspace\MySeleniumTests>mvn clean test -Dwebdriver.firefox.bin="C:\Program Files\Mozilla\Firefox\firefox.exe"
I have used jbehave-maven-plugin. Maven picks up all the Embedder impl (JunitStories in my case) from the source directory and execute them one by one. Configuration for that is <include>**/*Stories.java</include> in pom.xml
It then looks for relevant .story files in the specified dir and executes them. Say, I have two story files one.story and two.story, both of them are executed.
Over a time, number of story files are going to increase I only want to execute specific story files should there be a way to do this? I am thinking to pass specific story file names as run time parameters but don’t know what is required to make that happen.
I got it working with the below code
mvn clean test -Dwebdriver.firefox.bin="C:\Program Files\Mozilla\Firefox\firefox.exe" -Dstory=myStory.story
Override storyPaths() method in embedder class as below.
public class MyTestStories extends JUnitStories /* InjectableEmbedder */{
#Override
protected List<String> storyPaths() {
List<String> storiesToRun = new ArrayList<String>();
String storyProperty = System.getProperty("story");
if (storyProperty == null || storyProperty.isEmpty()) {
throw new RuntimeException("Please specify which stories to run");
}
String[] storyNames = storyProperty.split(",");
StoryFinder sf = new StoryFinder();
URL baseUrl = CodeLocations.codeLocationFromClass(this.getClass());
for (String storyName : storyNames) {
storiesToRun.addAll(sf.findPaths(baseUrl, storyName, ""));
}
return storiesToRun;
}
Try the following:
mvn clean test -Dwebdriver.firefox.bin="C:\Program Files\Mozilla\Firefox\firefox.exe" -Djbehave.story.name=<story filename without extension (wildcards are supported)>
You should also use custom test suite implementation:
public abstract class JBehaveTestSuite extends ThucydidesJUnitStories {
private static final String STORY_NAME_PATTERN = "**/${jbehave.story.name:*}.story";
public JBehaveTestSuite() {
findStoriesCalled(storyNamesFromEnvironmentVariable());
}
#Override
public void run() throws Throwable {
super.run();
}
private String storyNamesFromEnvironmentVariable() {
return SystemPropertyUtils.resolvePlaceholders(STORY_NAME_PATTERN);
}
}