Hot questions for Using Cucumber in webdriver

Question:

After doing a fair amount of research on how to run Cucumber test cases in parallel, I found the following very useful article on the subject matter:

https://www.opencredo.com/2013/07/02/running-cucumber-jvm-tests-in-parallel/

The article has some pretty good information to get you started working with a multi-threaded environment, including some code you can download from Github.

https://github.com/tristanmccarthy/Cucumber-JVM-Parallel

If I understand the article correctly the driver should be configurable to work with Grid, enabling you to run multiple test cases across multiple devices. After doing some testing with the code using a chromedriver, it does seem to work as described in the article. However, once it is configured to work with Grid the test cases no longer get executed in parallel. Instead, they are executed sequentially.

Currently, I have Grid configured to have 1 hub and 2 nodes. Each node can have a maximum of 2 sessions at any given time.

Note: Without Cucumber I'm able to successfully deploy multiple test cases across multiple devices, So I don’t think the problem is related to my grid setup.

Here is a sample of the code related to the web driver:

static {
    DesiredCapabilities capabilities = new DesiredCapabilities();
    capabilities.setJavascriptEnabled(true);
    capabilities.setBrowserName("chrome");
    capabilities.setPlatform(Platform.ANY);
    try {
        REAL_DRIVER = new RemoteWebDriver(new URL("http://xxx.xxx.xxx.xxx:4444/wd/hub"), capabilities);
    } catch (MalformedURLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    REAL_DRIVER.manage().timeouts().pageLoadTimeout(3000, TimeUnit.SECONDS);
    REAL_DRIVER.manage().window().maximize();
    Runtime.getRuntime().addShutdownHook(CLOSE_THREAD);
}

public SharedDriver() {
    super(REAL_DRIVER);
}

@Override
public void close() {
    if (Thread.currentThread() != CLOSE_THREAD) {
        throw new UnsupportedOperationException(
                "You shouldn't close this WebDriver. It's shared and will close when the JVM exits.");
    }
    super.close();
}

I suspect that if you use more than one browser type that you should be able to run the test cases on multiple devices (1 browser per device), but in my case I am on using Chrome driver. Does anyone know what might be preventing the test cases from being distributed across multiple devices or have any better understanding of how Grid works with cucumber? Please share any articles or information related to this problem.


Answer:

Grid doesn't do anything about splitting jobs up. It took me awhile (and a lot of scotch) to finally realize all Grid does is take a job from somewhere and pass it to an available node.

You need a test runner that will split your feature/scenario tests in to different chunks to pass to Grid. Unfortunately, the Cucumber runner doesn't do that. There are several different ways to split those tests into separate jobs to pass to the Grid.

That OpenCredo blog points to a newer post that uses Maven. Make sure to check that out!

Someone mentioned TestNG. I've not used it, so I can't comment on it.

You can split up your features/scenarios yourself and pass jobs separately to your Grid by running different test passes--that's cumbersome for long-term maintainability, but it's a quick start.

We wrote a small runner that scans scenarios and dynamically passes them to the Grid. Can't share code because it's at work and I'm in my hotel...

One thing to keep in mind: you'll have to manage dependencies and concurrency issues. Hopefully you're structuring tests so there's no dependencies between them. Concurrency's a different matter. We've got a bit of code that hands unlocked resources to the tests (think users, data sets, etc.)

Good luck!

Question:

I've being trying to integrate cucumber-jvm with selenium webdriver (firefox) but after I made it to run my tests now I'm seeing a lot to debug logs from selenium I think.

Here is my current structure.

My build.sbt dependencies added:

  "info.cukes" % "cucumber-java" % "1.2.4",
  "info.cukes" % "cucumber-junit" % "1.2.4",
  "info.cukes" % "cucumber-picocontainer" % "1.2.4",
  "org.seleniumhq.selenium" % "selenium-java" % "2.48.2"

Software Deps:

Centos 6 64bit.
Firefox "Mozilla Firefox 31.3.0"
Java java version "1.8.0_45" (build 1.8.0_45-b13)

FirefoxDriver Instantiation:

@Before
public void setUp() throws Exception {
    if (driver == null) {
        driver = new FirefoxDriver();
        driver.navigate().to(base_url);
        driver.manage().deleteAllCookies();
   }
}

Junit Runner:

@RunWith(Cucumber.class)
@CucumberOptions(
    features="test/acceptance/features",
    glue={"context"},
    plugin={"html:cucumberReport"}
)
public class CucumberRunnerTest {
}

How am I running the tests:

./activator clean compile test

The kind of logs I'm getting:

16:11:54.212 [Forwarding newSession on session null to remote] DEBUG o.a.h.c.protocol.RequestAddCookies - CookieSpec selected: default
16:11:54.213 [Forwarding newSession on session null to remote] DEBUG o.a.h.c.protocol.RequestAuthCache - Auth cache not set in the context
16:11:54.213 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection request: [route: {}->http://127.0.0.1:7056][total kept alive: 0; route allocated: 0 of 2000; total allocated: 0 of 2000]
16:11:54.213 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection leased: [id: 16][route: {}->http://127.0.0.1:7056][total kept alive: 0; route allocated: 1 of 2000; total allocated: 1 of 2000]
16:11:54.213 [Forwarding newSession on session null to remote] DEBUG o.a.h.impl.execchain.MainClientExec - Opening connection {}->http://127.0.0.1:7056
16:11:54.213 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.DefaultHttpClientConnectionOperator - Connecting to /127.0.0.1:7056
16:11:54.214 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.DefaultHttpClientConnectionOperator - Connection established 127.0.0.1:39264<->127.0.0.1:7056
16:11:54.214 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-16: set socket timeout to 10800000
16:11:54.214 [Forwarding newSession on session null to remote] DEBUG o.a.h.impl.execchain.MainClientExec - Executing request POST /hub/session HTTP/1.1
16:11:54.214 [Forwarding newSession on session null to remote] DEBUG o.a.h.impl.execchain.MainClientExec - Target auth state: UNCHALLENGED
16:11:54.214 [Forwarding newSession on session null to remote] DEBUG o.a.h.impl.execchain.MainClientExec - Proxy auth state: UNCHALLENGED
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> POST /hub/session HTTP/1.1
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> Content-Type: application/json; charset=utf-8
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> Content-Length: 105
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> Host: 127.0.0.1:7056
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> Connection: Keep-Alive
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> User-Agent: Apache-HttpClient/4.5.1 (Java/1.8.0_45)
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 >> Accept-Encoding: gzip,deflate
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "POST /hub/session HTTP/1.1[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "Content-Type: application/json; charset=utf-8[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "Content-Length: 105[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "Host: 127.0.0.1:7056[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "Connection: Keep-Alive[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "User-Agent: Apache-HttpClient/4.5.1 (Java/1.8.0_45)[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "Accept-Encoding: gzip,deflate[\r][\n]"
16:11:54.215 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "[\r][\n]"
16:11:54.216 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 >> "{"desiredCapabilities":{"browserName":"firefox","version":"","platform":"ANY"},"requiredCapabilities":{}}"
16:11:54.307 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "HTTP/1.1 200 OK[\r][\n]"
16:11:54.307 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "content-type: application/json; charset=UTF-8[\r][\n]"
16:11:54.307 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "connection: close[\r][\n]"
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "content-length: 421[\r][\n]"
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "server: httpd.js[\r][\n]"
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "date: Thu, 10 Dec 2015 16:11:54 GMT[\r][\n]"
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "[\r][\n]"
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << HTTP/1.1 200 OK
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << content-type: application/json; charset=UTF-8
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << connection: close
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << content-length: 421
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << server: httpd.js
16:11:54.308 [Forwarding newSession on session null to remote] DEBUG org.apache.http.headers - http-outgoing-16 << date: Thu, 10 Dec 2015 16:11:54 GMT
16:11:54.310 [Forwarding newSession on session null to remote] DEBUG org.apache.http.wire - http-outgoing-16 << "{"name":"newSession","sessionId":"d1aa222a-0c82-46a6-a0dd-80942dc13274","status":0,"value":{"cssSelectorsEnabled":true,"browserName":"firefox","handlesAlerts":true,"javascriptEnabled":true,"nativeEvents":false,"platform":"Linux","rotatable":false,"takesScreenshot":true,"version":"31.3.0","webStorageEnabled":true,"applicationCacheEnabled":true,"databaseEnabled":true,"locationContextEnabled":true,"acceptSslCerts":true}}"
16:11:54.310 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-16: Close connection
16:11:54.310 [Forwarding newSession on session null to remote] DEBUG o.a.h.impl.execchain.MainClientExec - Connection discarded
16:11:54.310 [Forwarding newSession on session null to remote] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Connection released: [id: 16][route: {}->http://127.0.0.1:7056][total kept alive: 0; route allocated: 0 of 2000; total allocated: 0 of 2000]

I'm new to jvm-cucumber and play please I would be very glad if someone could help me :) I'll keep you posted if I got anything new.

Update:

I don't know why but the "Before" and the "Given" clauses don't print any debug logs. Any other do.


Answer:

For my Maven project with cucumber and webdriver the solution was to add a file to "/resources/logback.xml" with the same content as below.

So it should be able to do the same for the playframework. Create a "conf/resources/logback.xml" with the content:

<configuration debug="false">
  <!-- definition of appender STDOUT -->
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>%-4relative [%thread] %-5level %logger{35} - %msg %n</pattern>
    </encoder>
  </appender>

  <root level="ERROR">
    <!-- appender referenced after it is defined -->
    <appender-ref ref="STDOUT"/>
  </root> 
</configuration>

(Source: https://stackoverflow.com/a/8936580/2827420)

Question:

I've searched a bit for this but can't find an exact example. I have a form to fill in as a step. The form fields look something like this:

Date: Currency: Total: Description:

But not all of the fields are required to have data entered by the user. Instead of writing several methods to account for the different combinations, like so:

(When I enter the 'Date' and 'Currency' and 'Total' and 'Description')  
(When I enter the 'Date' and 'Total')  
(When I enter the 'Currency' and 'Description')  
etc...

I'd like to somehow implement something like this, instead, in the feature file:

When I enter the following details:  
  |Date        |x    |       
  |Currency    |USD  |  
  |Total       |100  |   
  |Description |Test |  

And then have a single method to handle any combination of data the user enters in that second column.

I've found sites that have this data table-driven example:

When I enter the following details:  
  |Date        |<date>        |       
  |Currency    |<currency>    |  
  |Total       |<total>       |   
  |Description |<description> |  

Example data:
  |date |currency |total |description |  
  |x    |USD      |100   |foo         |
  |y    |EUR      |200   |test        |
  |z    |HKD      |124   |bar         |

But that's not what I am after. I don't need to iterate through a list of predetermined example data. I hope I've summarized the problem clearly enough and someone knows a good place to go find an example of this kind of implementation. Thanks for any advice!


Answer:

Yes, you can use a data table as an argument to a single non-repeated step. The first row of the data table must be a header:

When I enter the following details:
  |Name        |Value|
  |Date        |x    |
  |Currency    |USD  |
  |Total       |100  |
  |Description |Test |

Here's one possible way to use it in a step:

@Given("^I enter the following details:$")
public void i_enter_the_following_details(Map<String, String> details) throws Throwable {
    for Map.Entry<String, String> entry : details.entrySet() {
        String key = entry.getKey();
        String value = entry.getValue();
        switch (key) {
            case "Date":
                // add the date to the form
                break;
            // ...
        }
    }
}

You can also get the table as a DataTable, a List of value objects, a List<List<String>> or a List<Map<String>> by declaring the parameter with that type. Map<String, String> seems easiest here.

I wrote the example this way because I'm assuming that you need to write different code to put each value in its field. If the code is the same for every field you might be able to just put the field's CSS selector in the data table and get rid of the switch.

More examples are here and here.

Question:

Does anyone knows why Minium (Selenium Webdriver Java + Cucumber) is throwing this error trace?

I have been looking for hours and nothing seems to fix this error.

Proyect structure

Java:

import minium.cucumber.MiniumCucumber;

import java.io.IOException;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.cli.Main;
import ModulosComunesWeb.*;

@RunWith(MiniumCucumber.class)
/*@CucumberOptions(
        features = "LO-PPE-WEB-AltaFavoritos.feature"
    //  ,glue={"stepDefinition"}
        )
@CucumberOptions(

        features= "LO-PPE-WEB-AltaFavoritos.feature"
)*/
public class LOFavoritasIT {


}

2018-07-10 12:35:08.977 WARN 17180 --- [engine-thread-0] minium.cucumber.internal.MiniumBackend : Could not load glue src/test/resources/steps

org.mozilla.javascript.WrappedException: Wrapped org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'browser' defined in minium.web.config.WebElementsConfiguration: Unsatisfied dependency expressed through method 'browser' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'wd' defined in minium.web.config.WebElementsConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.openqa.selenium.WebDriver]: Factory method 'wd' threw exception; nested exception is java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see https://github.com/SeleniumHQ/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://chromedriver.storage.googleapis.com/index.html (minium/minium.js#23) at org.mozilla.javascript.Context.throwAsScriptRuntimeEx(Context.java:1893) at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:148)


Answer:

You need to check your Google Chrome browser version to download the chromedriver that match the browser version. If you are not using the latest version, download the chromedriver that match your browser version and copy the ".exe" file to the drivers folder of Minium Developer.

If you have the latest Google Chrome browser version, Minium Developer can download the latest webdrivers for you: https://minium.vilt.io/docs/developer/minium-developer/#update-webdrivers

Question:

After passing all test cases( aka scenarios in Cucumber), I'm trying to invoke a method using @After hook Cucumber capability in order to open a report file in Chrome browser. The idea is to display a report file using Selenium WebDriver after all tests are passed. When the Cucumber invokes this @After hook method, Selenium starts, gets this path, but the Chrome doesn't open the report file. Chrome says "Your file was not found It may have been moved or deleted. ERR_FILE_NOT_FOUND". But if then I manually click on reload button, the file opens successfully. Please help me when you are familiar with Cucumber and Selenium. Thank you in advance. P.S. Yes, I also tried to replace '\' by '/'

When Selenium tries to access that report html file: chrome screenshot

My Java code is:

@After
public void afterScenarios(){
          System.setProperty("webdriver.chrome.driver", "C:\\Users\\Testing\\BrowserDrivers\\chromedriver_win32\\chromedriver.exe");
          driver = new ChromeDriver();
          driver.manage().window();
          System.out.println("Opening the report...");
          driver.get("C:\\Users\\target\\cucumber-report\\business-acceptance-test1\\index.html");

}

Answer:

The reporting process is not fully complete when the After hook is executing. Try placing the selenium code in a JVM shutdown hook. This will make sure everything is completed.

Runtime.getRuntime().addShutdownHook(new Thread()......);

Refer to this - https://www.geeksforgeeks.org/jvm-shutdown-hook-java/

Question:

I am trying to automate a scenario by using Maps in Cucumber DataTable using multiple test data. In this test we will pass Username and Password two times to the test step. So our test should enter Username & Password once, click on LogIn button and repeat the same steps again.

I have tried using a for loop to repeat the test using Maps collection. 1. I am getting an error saying Type mismatch: cannot convert from element type Map<Object,Object> to Map<String,String> 2. When i convert it into Map<Object, Object>, I get another error saying The method sendKeys(CharSequence...) in the type WebElement is not applicable for the arguments (Object)

    Feature File Scenario
    Scenario: Successful Login with Valid Credentials
     Given User is on Home Page
     When User Navigate to LogIn Page
     And User enters Credentials to LogIn
     | Username   | Password |
        | testuser_1 | Test@153 |
        | testuser_2 | Test@154 |
     Then Message displayed Login Successfully

Step Definition
//Maps in Data Tables with Multiple Test Data


    @Then("^user enters Credentials in LogIn$")
        public void user_enters_username_and_password(DataTable userCredentials) throws Throwable {
            //Write the code to handle Data Table
             for (Map<String, String> data : userCredentials.asMaps(String.class, String.class) ) {
            driver.findElement(By.xpath("//input[@type='text']")).sendKeys(data.get("username"));
            driver.findElement(By.name("password")).sendKeys(data.get("password"));
            }
        }

Expected - convert from element type Map to Map Actual - Type mismatch: cannot convert from element type Map to Map


Answer:

Can you try assign result to intermediate variable first?

List<Map<String, String>> rows = userCredentials.asMaps(String.class,  String.class);
for (Map<String, String> data : rows) {
  ...
}

Question:

Using Selenium and Cucumber, I'm trying to setup a method to store WebElements through args. Then with a second method, I'm trying to check the visibility of all elements on the list.

I have some elements located this way:

 @FindBy(how = How.XPATH, using = "//* 
 [@id=\"content\"]/section/fieldset/form/div[1]/div[2]/input")
 public WebElement formName;
 @FindBy(how = How.CSS, using = "//* 
 [@id=\"content\"]/section/fieldset/form/div[2]/div[2]/input")
 public WebElement formPassword;
 @FindBy(how = How.ID, using = "remember")
 public WebElement rememberMe;
 @FindBy(how = How.CLASS_NAME, using = "button principal")
 public WebElement loginButton;

Then I wrote this method to add WebElements in a list:

public void crearListaWebElement(WebElement... elements){
    List<WebElement> webElementList = new ArrayList<>();
    for (WebElement element : elements){
        webElementList.add(elements);
    }
}

Getting this error on .add(elements) 1º issue:

add (java.util.Collection) in List cannot be applied to (org.openqa.selenium.WebElement[])

Cannot figure out why i can't add these same-type elements to my List

Then, here is the second method to check visibility:

public void estaVisible(WebDriver(tried WebElement as well) visibleWebElements) {

    boolean esvisible =  driver.findElement(visibleWebElements).isDisplayed();
    Assert.assertTrue(esvisible);
    return esvisible;
}

Getting this error on "visibleWebElement":

findElement (org.openqa.selenium.By) in WebDriver cannot be applied to (org.openqa.selenium.WebDriver)

I understand the conflict between the 2 different types of object, but, aren't the objects found by WebDriver stored as WebElements?

Could someone put some light overhere please? Thanks in advance.  


Answer:

When you try to check the list of Web elements you have to check with the visibility of all elements.Try with the below code

WebDriverWait for list of web elements

Store all the elements in a list

List<WebElement> listOfAllWebElements = new ArrayList<WebElement>();
listOfAllWebElements.add(elementOne);
listOfAllWebElements.add(elementTwo);
listOfAllWebElements.add(elementThree);

WebDriverWait listWait = new WebDriverWait(driver,10);
listWait.until(ExpectedConditions.visibilityOfAllElements(listOfAllWebElements));

WebDriverWait for single web element

WebElement element = driver.findElement(By.id("element"));

WebDriverWait wait = new WebDriverWait(driver,10);
wait.until(ExpectedConditions.visibilityOf(element));

Question:

I have 8 cucumber-jvm scenarios and the very first scenario measures the page load time and environment availability. In order to avoid unnecessary runs, if the first scenario is failed - for instance, the environment is not available, or loading too slowly - all other scenarios should be skipped.

How can I do that?

My CucumberOptions:

@RunWith(Cucumber.class)
@CucumberOptions(
        strict = true,
        features = {"src/test/resources/features"},
        glue = {"stepDefinitions"},
        format = {  "progress", "html:target/Results",
                "json:target/Results/cucumber.json"},
        tags = {"@test"})
        public class TestRunner {
}

Thanks!


Answer:

You can make use of Assume.assumeTrue(false) to skip tests. But this will require some changes in test runner and code changes.

  1. Create a separate runner for the scenario which checks the environment details are all working. Let's call it RunFirstTest.java and give tags a value of @Smoke. Other option values default to what you have.
@RunWith(Cucumber.class)
@CucumberOptions(plugin={ }, tags={"@Smoke"}, glue=" ", features=" ")
public class RunFirstTest {
  1. Add the @Smoke tag to the scenario in the feature file that checks the environment etc. Optionally you could look at splitting the feature files.

  2. Create a new class to hold a static flag. It is a simple implementation you might look at making this more robust.

public class SkipFlag {   
     public static boolean skipFlag = false; }
  1. Create an After hook with the value option set to @Smoke. Thus it will run only for the smoke scenario.
@After(value={"@Smoke"})  
public void afterSkip(Scenario scen) {        
   if(scen.isFailed())            
      SkipFlag.skipFlag = true;   
}
  1. Create a second runner for the main tests. Let's call it RunMainTest.java and give its tags value of @MainTests. Other option values default to what you have.

@RunWith(Cucumber.class) @CucumberOptions(plugin={" "}, tags={"@MainTests"}, glue=" ", features=" ") public class RunMainTest { @BeforeClass public static void before() { if(SkipFlag.skipFlag) Assume.assumeTrue(false); } }

  1. Add the @MainTests tag to the other scenarios in the feature file. Optionally you could look at splitting the feature files and give the name of the feature file in the features option value.

  2. Run this by using maven failsafe plugin. In the configuration of this plugin add the inclusion of these 2 runners in the pom.xml.

 <configuration>
      <includes>
          <include>RunFirstTest</include>
          <include>RunMainTest</include>
      </includes>
        <runOrder>alphabetical</runOrder>
 </configuration>

The includes part might be optional if you only have 2 runners. The most important point is that the RunFirstTest should be the first to run, so alphabetically should be first.

  1. Run it with maven.

Hope it works.

Question:

I am currently working on a project and I am looking for a way to automate the programming system. In a nutshell, the project works in this way: some operations on the frontend (www site) call and generate logs (with a lot of content) and now I analyze the logs manually but I would like to automate this process.

I have a question for you how to approach this process in the simplest way, I am currently learning java and for now, I wrote scripts in selenium webdriver + java and cucumber. And here is my question whether using cucumber I could also add assertions to verify logs? if so, how?

At the moment I have three ways to verify my logs:

  1. after performing some operations on the website, reading a file with logs from the location on the C drive of my computer and verify if there is a corresponding string in the file.
  2. Performing all operations on the frontend and generating full logs, and then comparing them with the template file with logs (one that is tested manually and it is certain that the entire page functionality works correctly)
  3. I am also thinking about such a solution to download a text file in time eg. in a loop such as 20 seconds and check if there is the desired string in it and then in the cucumber is considered assertion.

I am asking for advice from more experienced colleagues.

For all the tips, I will be very grateful!

Greetings, Chris


Answer:

I would separate out the testing of logging from the testing of business functionality. With logging there are two main things you might want to check

  1. That an operation causes a log entry to be written
  2. That the content of a particular log entry is correct

You can do this at a very low level very fast with a unit test around each log call that your code makes. This will give you a suite of a large number of very tests each one testing that one log entry is made.

If you continue with your current approach you will be running integration tests (which will be much much slower) where each business action generates large amounts of logging. Some of that logging will be your logging but lots of it will probably be logging from your platform, which you don't need to test. This approach is error prone, complex and does not give very good value.

Question:

I try to write a selenium test cases in java and I am having a problem. The test involves a click on a drop down menu. But I can't reach this...

Here are my steps. First I go to the german wikipedia:

@Given("^You want to search for \"Baum\" on \"([^\"]*)\"$")
public void youWantToSearchForOnWikipediaOrg(String page) throws Throwable
{
    System.setProperty("webdriver.chrome.driver",
            "C:\\...\\chromedriver_win32\\chromedriver.exe");
    driver = new ChromeDriver();
    driver.get("https://"+page+"/wiki/Wikipedia:Hauptseite");
}

Then I search for the word "Baum":

@Then("^You tipp the letters \"([^\"]*)\", \"([^\"]*)\" and \"([^\"]*)\"$")
public void youTippTheLettersAnd(String letter1, String letter2, String letter3) throws Throwable
{
    Thread.sleep(5);
    driver.findElement(By.xpath("//input[@id='searchInput']")).sendKeys(letter1);
    driver.findElement(By.xpath("//input[@id='searchInput']")).sendKeys(letter2);
    driver.findElement(By.xpath("//input[@id='searchInput']")).sendKeys(letter3);
    Thread.sleep(25);
}

Now a dropdown menu appaers an I want to click on the entry "Baum".

@Then("^Click on the appearing Baum$")
public void clickOnTheAppearing() throws Throwable
{
    //Thread.sleep(50);
    driver.findElement(By.xpath("//a/div")).click();
}

But xpath can't find the element. I try different xpath and css, but nothing helps...

Examples:

//*[@classname='mw-searchSuggest-linkinput']//*[text()='Baum']

/html/body/div[6]/div/a[1]/div/span

/html/body/div[6]/div/a[1]/div

body > div.suggestions > div > a:nth-child(1) > div > span

The website:


Answer:

You just need to put some wait and after that element load use the following:

Thread.sleep(3000);

driver.findElement(By.xpath(".//a[@title='Baum']")).click();

Hope it helps you!

Question:

I am trying to run Cucumber test scenarios (java project) through Gradle by following reference link-https://docs.cucumber.io/tools/java/#build-tools

This is my Build.gradle file

.output of command gradle build

this is showing scenarios are being recognized but WebDriver is not invoking and reports(build/tests/test/index.html) are showing zero. I am very new to both gradle and cucumber and stuck in my first gradle project. help will highly appreciated.


Answer:

Change the glue parameter in task from "gradle.cucumber" to the classpath where your stepdefinitions are present. Switch to org.projectName.appname.tests and try

gradle.cucumber was the location of the package of stepdefinitions specific to the article.

Question:

I am very new to Cucumber and get the following error using ChromeDriver to request a URL:

java.lang.IllegalStateException: The path to the driver executable must be set by the webdriver.chrome.driver system property; for more information, see http://code.google.com/p/selenium/wiki/ChromeDriver. The latest version can be downloaded from http://chromedriver.storage.googleapis.com/index.html at com.google.common.base.Preconditions.checkState(Preconditions.java:177)

My code:

package cucumber.features;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class AddToList {

    WebDriver driver = null;

    @Given("^I am on Todo site$")
    public void onSite() throws Throwable {
        driver = new ChromeDriver();
        driver.navigate().to("http://localhost");
        System.out.println("on todo site");

    }

    @When("^Enter a task in todo textbox$")
    public void enterTask() throws Throwable {
        driver = new ChromeDriver();
        driver.findElement(By.name("task")).sendKeys("Test Unit Using Cucumber");
        ;
        System.out.println("task entered");
    }

    @Then("^I click on add to todo$")
    public void clickAddToTodo() throws Throwable {
        driver = new ChromeDriver();
        driver.findElement(By.xpath("//input[@value='Add to Todo' and @type='button']"));
        System.out.println("add button clicked");

    }

}

Answer:

I had a similar problem when using selenium library. I found this line before creating my driver fixed it.

System.setProperty("webdriver.chrome.driver", PATH_TO_CHROME_DRIVER);

Here is simple project that could help you.

Question:

Consider I have to do a Google search on a Macbook and I have to navigate through the search results page until I find the eBay link.

For example, if the eBay link is in the 3rd page of the search results page in Google, then my Selenium script should be clever enough to realize that pages 1 & 2 don't contain the eBay link and in the 3rd page it should click on the eBay link.

My pseudo-code tries to identify the eBay link using driver.findElement(By.LinkText("Ebay.co.uk")), but I am unsure how find the eBay link among search results page.

All I have tried is the following pseudo-code:

if (driver.isLinkPresent("Ebay.co.uk")) {
    then driver.findElement(By.linkText(Ebay)).click();
    Else 
            Navigate to next Search result page
})(Repeat the loop until the link is found);

Any ideas on how to take this to code level? Glad if anyone could help!


Answer:

I'll be able to show you how, but as I have not used selenium with Java, I won't be able to provide the exact code.

Here's the pseudo code:

found = false;

while(found == false){

   attemptFind = $driver.findElements({xpath: "//h3[contains(text(),'eBay: Electronics')]"}); // Returns an array of headers are found with Ebay.co.uk in

   if attemptFind.length() == 0 || attemptFind == null {
      currentPage = $driver.findElement({css: "td.cur"}).getText(); // Get Current Page Number
      nextPage = (currentPage.toInt() + 1).toString(); // Add 1 to current page

      $driver.findElement({css: "a[aria-label='Page "+nextPage+"']"}).click(); // Go to next page
   } else {
      attemptFind[0].click(); // Click on the Ebay link
      found = true; // Break out of loop
   }
}

Question:

I want to do test on my application, so first scenario is the authentification, once done, i need to make test on the next page which is the home page, so how can i use the same driver without restarting my driver in the second scenario ? I want to start directly from : @given I'm on the home page!

I have a class for stepdefauthentification, another one for stepdefSearchCustomer, so how can i use my driver from the first class in the second ? The initialisation of the chromedriver is in the first page, and i can't even restart my driver by doing : driver.geturl("") in the second because we need to authentify first so that the home page will display .

which means i need to recuperate the driver with it's url from the first scenario and then start from there in the second one .


Answer:

  1. Your scenarios should NOT depend on each other, your scenarios should be autonomous, before ruining particular scenario, you should prepare all the conditions it needs to execute it, and preferably, clear after scenario as well.

  2. To preserve browser window for multiple scenarios, make your WebDriver instance static, you can use Singleton Holder pattern for example.

I understand your issue, to test main page, you need to be logged in, so naturally you might think that executing scenarios in order would solve it, but its bad approach.

Instead, to test main page, either load cookies into web driver so it thinks that you are already logged into the session, or alternatively, you can create 'before' @Login hook that can check, if you are logged in, if not it would run login procedure, before running scenario.

@Before(value = "@Login")
public void loginIfNeeded()
{
    // check you are logged in, if you are, do not login
    // if you are not logged in, perform login procedure.
}

Sample scenario:

@Login
Scenario: Test main page
  Given something
  When something
  Then something

Question:

I was trying to automate a few sample Test Scenarios using Page Factory Model and Cucumber but don't seem to understand why multiple driver instances when I try to run a single test case.

When I am trying to run only Test Case 1 through Runner.java file

package execution;

import java.io.File;

import org.junit.AfterClass;
import org.junit.runner.RunWith;

import com.cucumber.listener.Reporter;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(features = "D:\\Eclipse Wokspace\\EcommerceProject\\Features\\Test1.feature", 
                 glue = { "stepDefinition" }, 
                 plugin = { "html:target/cucumber-html-report",
        "pretty:target/cucumber-pretty.txt", "usage:target/cucumber-usage.json",
        "junit:target/cucumber-results.xml","com.cucumber.listener.ExtentCucumberFormatter:target/cucumber-reports/report.html" }, 
                 dryRun = false, 
                 monochrome = true, 
                 strict = true)
public class Runner {
    @AfterClass
    public static void writeExtentReport() {
        Reporter.loadXMLConfig(
                new File("D:\\Eclipse Wokspace\\EcommerceProject\\src\\test\\resources\\extent-config.xml"));
        Reporter.setSystemInfo("User Name", System.getProperty("user.name"));
        Reporter.setSystemInfo("Time Zone", System.getProperty("user.timezone"));
        Reporter.setSystemInfo("Machine", "Windows 10 " + "64 Bit");
        Reporter.setSystemInfo("Selenium", "3.7.0");
        Reporter.setSystemInfo("Maven", "3.5.2");
        Reporter.setSystemInfo("Java Version", "1.8.0_151");
    }
}

@Before and @After of other two Step Definition classes also seem to be invoked as visible from the logs below

2018-08-05 14:16:16,358  INFO [main] SameCostSteps:25 - ************* Test Case 2 Begin ***************
2018-08-05 14:16:31,264  INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:16:31,321 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:16:33,077  INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:16:33,083  INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:16:33,123  INFO [main] CartLimitSteps:26 - ***************************************************************
2018-08-05 14:16:33,126  INFO [main] CartLimitSteps:27 - ******************** Test Case 3 Begin ************************
2018-08-05 14:16:33,127  INFO [main] CartLimitSteps:28 - ***************************************************************
2018-08-05 14:16:47,370  INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:16:47,371 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:16:48,771  INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:16:48,773  INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:16:48,777  INFO [main] SortByNameSteps:24 - ************* Test Case 1 Begin ***************
2018-08-05 14:17:01,832  INFO [main] HomePage:17 - PageFactory setup of HomePage
2018-08-05 14:17:01,833 DEBUG [main] HomePage:22 - Click on Mobile Link
2018-08-05 14:17:03,563  INFO [main] HomePage:24 - Navigating to Mobile Page
2018-08-05 14:17:03,567  INFO [main] MobilePage:35 - PageFactory setup of MobilePage
2018-08-05 14:17:04,411  INFO [main] SortByNameSteps:40 - Retrieving initial unsorted product list
2018-08-05 14:17:04,411  INFO [main] MobilePage:47 - Collecting a list of Products
2018-08-05 14:17:04,872  INFO [main] MobilePage:41 - Selecting value from the dropdown list
2018-08-05 14:17:06,332  INFO [main] SortByNameSteps:48 - Retrieving final sorted list
2018-08-05 14:17:06,333  INFO [main] MobilePage:47 - Collecting a list of Products
2018-08-05 14:17:06,453  INFO [main] SortByNameSteps:51 - Sorting the unsorted array string by Name
2018-08-05 14:17:06,454  INFO [main] SortByNameSteps:53 - Verifying that the products have been sorted by Name
2018-08-05 14:17:06,454  INFO [main] MobilePage:58 - Verifying that the products have been sorted by Name
2018-08-05 14:17:06,459  INFO [main] SortByNameSteps:57 - ############# Test Case 1 Passed ###########
2018-08-05 14:17:06,463  INFO [main] SameCostSteps:33 - ************* Test Case 2 End ******************
2018-08-05 14:17:09,747  INFO [main] CartLimitSteps:37 - ***************************************************************
2018-08-05 14:17:09,749  INFO [main] CartLimitSteps:38 - ******************** Test Case 3 End   ************************
2018-08-05 14:17:09,750  INFO [main] CartLimitSteps:39 - ***************************************************************
2018-08-05 14:17:09,770  INFO [main] SortByNameSteps:33 - ************* Test Case 1 End   ***************

As visible from the log above @Before and @After is being executed for all the Step Definition Classes even one I am running only Test1.feature file.

I don't seem to understand why this is happening as it is causing a lot of browser instances to open unnecessarily.

Code for other classes is as follows :

Page Factory Classes:

A) HomePage.java

package pageFactory;

import org.apache.log4j.Logger;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

import Util.BasePage;

public class HomePage extends BasePage{
    Logger log = Logger.getLogger(HomePage.class);

    @FindBy(xpath="//*[@id=\"nav\"]/ol/li[1]/a")
    WebElement mobileLink;

    public HomePage() {
        log.info("PageFactory setup of HomePage");
        PageFactory.initElements(driver,this);
    }

    public MobilePage clickMobile() {
        log.debug("Click on Mobile Link");
        mobileLink.click();
        log.info("Navigating to Mobile Page");
        return new MobilePage();
    }
}

B) MobilePage.java

package pageFactory;

import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;

import Util.BasePage;

public class MobilePage extends BasePage {
    Logger log = Logger.getLogger(MobilePage.class);

    @FindBy(xpath = "//*[@id=\"top\"]/body/div/div/div[2]/div/div[2]/div[1]/div[3]/div[1]/div[1]/div/select")
    WebElement SortBy;

    @FindBy(xpath = "//h2[@class='product-name']/a")
    List<WebElement> products;

    @FindBy(xpath = "//*[@id=\"product-price-1\"]/span")
    WebElement xperiaPrice;

    @FindBy(id="product-collection-image-1")
    WebElement xperiaImg;

    @FindBy(xpath = "//*[@id=\"top\"]/body/div/div/div[2]/div/div[2]/div[1]/div[3]/ul/li[1]/div/div[3]/button")
    WebElement addToCartBtn;


    public MobilePage() {
        log.info("PageFactory setup of MobilePage");
        PageFactory.initElements(driver, this);
    }

    public void sortByIndex(int val) {
        Select dlSort = new Select(SortBy);
        log.info("Selecting value from the dropdown list");
        dlSort.selectByIndex(val);

    }

    public String[] retrieveProductNames() {
        log.info("Collecting a list of Products");
        String[] productList = new String[3];
        int i = 0;
        for (WebElement el : products) {
            productList[i] = el.getText();
            i++;
        }
        return productList;
    }

    public void verifySorting(String[] array1, String[] array2) {
        log.info("Verifying that the products have been sorted by Name");
        Assert.assertTrue(Arrays.equals(array1, array2), "The products have not been sorted proerly");
    }

    public String getXperiaPrice() {
        return xperiaPrice.getText();
    }

    public XperiaPage clickOnXperia() {
        xperiaImg.click();
        return new XperiaPage();
    }

    public ShoppingCartPage addToCart() {
        addToCartBtn.click();
        return new ShoppingCartPage();
    }

}

C) XperiaPage.java

package pageFactory;

import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

import Util.BasePage;

public class XperiaPage extends BasePage{
    @FindBy(xpath = "//*[@id=\"product-price-1\"]/span")
    WebElement xperiaPrice;

    public XperiaPage() {
        PageFactory.initElements(driver,this);
    }

    public String getXperiaPrice() {
        return xperiaPrice.getText();
    }
}

Step Definition Files

A) Test Case 1

package stepDefinition;

import java.util.Arrays;

import org.apache.log4j.Logger;

import Util.BasePage;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import pageFactory.HomePage;
import pageFactory.MobilePage;

public class SortByNameSteps {
    public HomePage objHomePage;
    public MobilePage objMobilePage;
    public Logger log = Logger.getLogger(SortByNameSteps.class);
    public String[] unsorted;
    public String[] sorted;

    @Before
    public void setup() {
        log.info("************* Test Case 1 Begin ***************");
        BasePage.initialization();
        objHomePage = new HomePage();
        objMobilePage = objHomePage.clickMobile();

    }

    @After
    public void tearDown() {
        log.info("************* Test Case 1 End   ***************");
        BasePage.closeSession();
    }

    @When("^Select Name from the DropDownList$")
    public void select_Name_from_the_DropDownList() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Retrieving initial unsorted product list");
        unsorted = objMobilePage.retrieveProductNames();
        objMobilePage.sortByIndex(1);
    }

    @Then("^Verify that the Products have been sorted by Name$")
    public void verify_that_the_Products_have_been_sorted_by_Name() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Retrieving final sorted list");
        sorted = objMobilePage.retrieveProductNames();

        log.info("Sorting the unsorted array string by Name");
        Arrays.sort(unsorted);
        log.info("Verifying that the products have been sorted by Name");

        try {
            objMobilePage.verifySorting(unsorted, sorted);
            log.info("############# Test Case 1 Passed ###########");
        }

        catch (Exception ex) {
            log.info("############# Test Case 1 Failed  ###########");
        }

    }

}

B) Test Case 2

package stepDefinition;

import org.apache.log4j.Logger;
import org.testng.Assert;

import Util.BasePage;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import pageFactory.HomePage;
import pageFactory.MobilePage;
import pageFactory.XperiaPage;

public class SameCostSteps {
    public HomePage home;
    public MobilePage mobile;
    public XperiaPage xperia;
    public String detailCost;
    public String listCost;
    public Logger log = Logger.getLogger(SameCostSteps.class);

    @Before
    public void tearUp() {
        log.info("************* Test Case 2 Begin ***************");
        BasePage.initialization();
        home = new HomePage();
        mobile = home.clickMobile();
    }

    @After
    public void tearDown() {
        log.info("************* Test Case 2 End ******************");
        BasePage.closeSession();
    }

    @When("^Read the cost of Sony Xperia$")
    public void read_the_cost_of_Sony_Xperia() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Fetching cost of product on List Page");
        listCost = mobile.getXperiaPrice();
    }

    @When("^Click on Sony Xperia Mobile$")
    public void click_on_Sony_Xperia_Mobile() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Clicking on Xperia");
        xperia = mobile.clickOnXperia();
    }

    @When("^Read Sony Xperia Cost on Details Page$")
    public void read_Sony_Xperia_Cost_on_Details_Page() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Fetching cost of product on Details Page");
        detailCost = xperia.getXperiaPrice();
    }

    @Then("^Verify That both the prices are same$")
    public void verify_That_both_the_prices_are_same() throws Throwable {
        // Write code here that turns the phrase above into concrete actions
        log.info("Verifying that the cost of products on both pages is same");
        try {
            Assert.assertEquals(detailCost, listCost);
            log.info("############# Test Case 2 Passed ###########");
        }

        catch (Exception ex) {
            log.info("Price of Xperia in List and Details Page is not same");
            log.info("############# Test Case 2 Failed ###########");
        }
    }
}

Base Page Class

package Util;

import java.util.Properties;
import java.util.concurrent.TimeUnit;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class BasePage {
    public static WebDriver driver = null;
    public static Properties prop;

    public static void initialization() {

        System.setProperty("webdriver.gecko.driver", util.FFDRIVER_PATH);
        driver = new FirefoxDriver();
        driver.manage().deleteAllCookies();
        driver.manage().timeouts().pageLoadTimeout(util.PAGELOAD_TIME, TimeUnit.SECONDS);
        driver.manage().timeouts().implicitlyWait(util.IMPICIT_WAIT, TimeUnit.SECONDS);
        driver.get(util.URL);
    }

    public static void closeSession() {
        driver.quit();
    }
}

Answer:

As discussed in comments, the problem was Cucumber is executing ALL the @Before and @After methods defined in the various classes of stepDefinition package. It is also the expected case since cucumber does not know which methods to execute unless you exclusively tell it to.

One simple solution to this would be to create different packages to hold different classes for each test case but as OP correctly pointed out that it would not be a feasible solution for like say 100 cases and this approach will limit the user to not be able to execute all the feature files from a single runner class.

Solution -

1) For this particular case, use @BeforeClass and @AfterClassJunit annotations instead of @Before and @After cucumber annotation. Since each test case Step Def has its own class, this should work for your case.

2) You can also use Tagged Hooks. It is basically attaching a hook to a name inside a scenario. Ex -

Feature file -

@Test1
Scenario: blah blah

@Test2
Scenario: blah blah 2

Step Definition -

    @Before("@Test1")
    public void beforeFirst(){
        //This will run only before the Scenario Test1
    }   

    @Before("@Test2")
    public void beforeSecond(){
       //This will run only before the Scenario Test2
    }

Question:

I am using Cucumber with Selenium WebDriver to test an application, and I have just noticed that my tests are passing on a particular area, no matter what I put into the parameters of the "ExpectedConditions.textToBe" method.

This part of the tests simple checks that the correct text appears in a table of user roles after the test has added a user:

    public void admin_can_see_the_new_role_in_the_list() throws Throwable {
    // Write code here that turns the phrase above into concrete actions
    //throw new PendingException();
    Thread.sleep(3000);
    ExpectedConditions.textToBe(By.xpath("//*[@id=\"role-nbbbamze\"]"), "account manasdfsdfger");
    ExpectedConditions.textToBe(By.xpath("//*[@id=\"app\"]/dizz/dib[2]/divz/div[2]zzz/table/tbody/tr[11]/td[2]"), "Accmasfsdnager");
    ExpectedConditions.textToBe(By.xpath("//*[@id=\"app\"]/dbiv/div[2]/div/dziv[2]/tzable/tzzzbody/tr[11]/td[3]"), "Can acvfcess the normal dashboard");
}

As you can see, I have added random characters to the parameters and the test runs and still passes. It should fail, either because the xpath I have defined doesn't exist - or the text I am asserting does not match anything within that xpath.

I am obviously using the ExpectedConditions wrong, but I can't figure out where or how.

Thanks in advance guys!


Answer:

You have to use it in combination with a wait object like:

WebDriverWait wait = new WebDriverWait(driver, 60); 
wait.until(ExpectedConditions.textToBe(By.xpath("//*[@id=\"app\"]/dbiv/div[2]/div/dziv[2]/tzable/tzzzbody/tr[11]/td[3]"), "Can acvfcess the normal dashboard"));

Question:

I have a doubt with the use of a login feature. What I look for:

I have a Login feature that should be used with all the rest of future features that I'm using with Cucumber and Selenium. This Login feature should concat with the rest of features.

This is mi Login.feature

Feature: Login Profile
  As an user of Page X
  I want to login my profile using my credentials
  In order to see the default dashboard

  Background: User navigates to Company home page
    Given I am on the Company login page

  @wip
  Scenario Outline: Successful login
    When I fill in User ID with "<username>"
    And I fill in Password with "<password>"
    And I click on the Log In button
    And I should get the Second code login with "<email>" and "<pass>"
    And I must put the Second code in the field code for accessing


    Examples:
      | username     | password | email              | pass    |
      | XXXXXXXX     | YYYYYYY  | ZZZZZZ@WWWWWW.com  | 1234556 |

I need to concat this feature with another new one without closing navigation in Selenium.

Could anybody guide me?


Answer:

See In Cucumber, steps defined under Scenario/Outline with in one Feature file can not be reused in other Feature files.

If you want to reuse login steps then you shall declare these under background in all those feature files where all scenarios shall reuse login steps written once under background in every feature file.

Example

Feature: Registration, Login and MyAccount
Background: User is Logged In
Given I am on the homepage
And I follow "Sign in"
@smoke
Scenario: Verify Login Functionality
When I fill "email address textbox" with "goswami.tarun77@gmail.com"
Then I fill "password textbox" with "Test1234"

Question:

Using Java I am implementing a Page Factory object for selenium testing that takes the name of a page object and instantiates it through reflection for use by Cucumber step definitions. The problem I am having is that the code below cannot find the declared class. Both the object PageFactory which contains this code and the page object LoginPage reside in a package called pages.

 /**
 * This method take a string containing a Page Object class name (case-sensitive) and returns an instance of the Page Object.
 * This allows us to operate on pages without knowing they exist when we write step definitions.
 * @param choice String
 * @return Page Object cast as a Page
 */
public static Page getPage(String choice) {
    Page entity = null;

    try {
        entity = (Page) Class.forName(choice).newInstance();
    } catch (InstantiationException e) {
        e.printStackTrace();
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    return entity;
}

I receive a stack trace with java.lang.ClassNotFoundException: LoginPage as the beginning of the error. If I change the entity creation to the following code, then it works.

        private static String packageName = "pages";
        entity = (Page) Class.forName(packageName + "." + choice).newInstance();

The problem is that I want to organize my pages. When I create pages.mywebsite and place LoginPage within that, PageFactory won't know where to find the file.

Leaving aside the problem that I could have two namespaces pages.mywebsite and pages.myotherwebsite that both have a LoginPage object, how can I find the files I want without declaring the exact package, and just say "Look in this package and the ones below for the class"?


Answer:

You could get the classpath using System.getProperty("java.class.path"), split it around File.pathSeparator, and scan the results using FileVisitor.

Question:

I'm working on webpage which displays warning message when Invalid username or password is entered. When the invalid details are entered, the message displayed will be changed and says user is blocked. I was trying to capture these different messages in a try/catch block. However, my code don't shift focus to else if block based on the warning message that I'm verifying.

Code:

driver.findElement(By.name("submitted")).click();

    try {           
             if (new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[@class='small-9 small-pull-1 column content']"), "No Password Found for"))){

            String text = driver.findElement(By.xpath("//*[@class='small-9 small-pull-1 column content']")).getAttribute("innerHTML");
            System.out.println(text);

            if(text.contentEquals("No Password Found for")){
        driver.navigate().refresh();

                Assert.fail("Unable to login to application");
            }
            }

             else if(new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[@class='small-9 small-pull-1 column content']"), "Your Online/Mobile Banking User ID has been blocked. Please go to "Forgot Password" option to unblock it."))){

String retext = driver.findElement(By.xpath("//*[@class='small-9 small-pull-1 column content']")).getAttribute("innerHTML");

            System.out.println(retext);

            if(retext.contentEquals("Your Online/Mobile Banking User ID has been blocked. Please go to "Forgot Password" option to unblock it.")) {
                driver.navigate().refresh();

                Assert.fail("Unable to login to application");
            }


        }       

             else if (new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[@class='small-9 small-pull-1 column content']"), "Time Out"))){
            String timeouttext = driver.findElement(By.xpath("//*[@class='small-9 small-pull-1 column content']")).getAttribute("innerHTML");

            if(timeouttext.contentEquals("You have specified an invalid User Name or Password. Please check and try again")){
                driver.navigate().refresh();

                                    Assert.fail("Unable to login to application");      }


        }

Answer:

Since your try includes all conditions, i assume that when it fails to find first element and throws exception, it skips all the rest body of try.

Do something like this:

try {
if (new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[@class='small-9 small-pull-1 column content']"), "No Password Found for")))
             {
                String text = driver.findElement(By.xpath("//*[@class='small-9 small-pull-1 column content']")).getAttribute("innerHTML");
                System.out.println(text);
                if(text.contentEquals("No Password Found for"))
                {
                    driver.navigate().refresh();
                    Assert.fail("Unable to login to application");
                }
            }
}
catch(Exception){}
try{
if(new WebDriverWait(driver, 10).until(ExpectedConditions.textToBePresentInElementLocated(By.xpath("//*[@class='small-9 small-pull-1 column content']"), "Your Online/Mobile Banking User ID has been blocked. Please go to "Forgot Password" option to unblock it.")))
             {
                String retext = driver.findElement(By.xpath("//*[@class='small-9 small-pull-1 column content']")).getAttribute("innerHTML");
                System.out.println(retext);
                if(retext.contentEquals("Your Online/Mobile Banking User ID has been blocked. Please go to "Forgot Password" option to unblock it.")) 
                {
                    driver.navigate().refresh();
                    Assert.fail("Unable to login to application");
                }
            }
catch(Exception){}

And so on.

Though, it will be better for performance to get text from this element, and evaluate it, instead of multiple attempts to find element.

Question:

Hi everybody: I'm trying to run Cucumber with Java (With Maven) and WebDriverManager (Bonigarcia)

This is the tree of my project:

    ├── maven_selenium_cucumber.iml
├── pom.xml
├── src
│   ├── main
│   │   ├── java
│   │   │   ├── common
│   │   │   │   └── BasePage.java
│   │   │   ├── pages
│   │   │   │   └── Page_First.java
│   │   │   └── util
│   │   │       └── driver
│   │   │           ├── Driver.java
│   │   │           └── DriverFactory.java
│   │   └── resources
│   │       ├── default.properties
│   │       └── log4j.properties
│   └── test
│       └── java
│           ├── features
│           │   └── first.feature
│           ├── runner
│           │   └── TestRunner.java
│           └── steps
│               └── Step_First.java
└── target

My Driver class (It acts like Hooks)

package util.driver;

import common.BasePage;
import cucumber.api.java.After;
import cucumber.api.java.Before;
import org.openqa.selenium.WebDriver;

import java.util.concurrent.TimeUnit;

public class Driver extends BasePage {


    public static WebDriver driver;


    @Before
    public void initializeDriver(){

        driver = DriverFactory.getDriver();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        driver.manage().window().maximize();

        if (driver == null) {
            log.info("Driver did not initialize correctly");
        }
    }


    @After
    public void closeDriver(){


        driver.quit();
        log.info("Driver closed");
    }
}

My DriverFactory class:

package util.driver;

import io.github.bonigarcia.wdm.WebDriverManager;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxBinary;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.firefox.FirefoxOptions;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.safari.SafariDriver;


public class DriverFactory {

    private static final String BROWSER = System.getenv("browser");
    private static final String WINDOW_WIDTH = System.getenv("window_width");
    private static final String WINDOW_HEIGHT = System.getenv("window_height");
    private static final String CHROME = "chrome";
    private static final String HEADLESS_CHROME = "headless-chrome";
    private static final String FIREFOX = "firefox";
    private static final String HEADLESS_FIREFOX = "headless-firefox";
    private static final String IE = "ie";
    private static final String EDGE = "edge";
    private static final String SAFARI = "safari";
    private static final String WINDOW_SIZE = "--window-size="+WINDOW_WIDTH+"x"+WINDOW_HEIGHT;

    private static WebDriver driver;


    public static WebDriver getDriver() {
        if (BROWSER == null) {
            WebDriverManager.chromedriver().setup();
            return new ChromeDriver();
        }
        switch (BROWSER.toLowerCase())
        {
            case CHROME:
                WebDriverManager.chromedriver().setup();
                return new ChromeDriver();
            case HEADLESS_CHROME:
                ChromeOptions chromeOptions = new ChromeOptions();
                chromeOptions.addArguments("--headless");
                chromeOptions.addArguments("start-maximized"); 
                chromeOptions.addArguments("disable-infobars"); 
                chromeOptions.addArguments("--disable-extensions"); 
                chromeOptions.addArguments("--disable-gpu"); 
                chromeOptions.addArguments("--disable-dev-shm-usage");
                chromeOptions.addArguments("--no-sandbox");
                return new ChromeDriver(chromeOptions);
            case FIREFOX:
                WebDriverManager.firefoxdriver().setup();
                return new FirefoxDriver();
            case HEADLESS_FIREFOX:
                FirefoxBinary firefoxBinary = new FirefoxBinary();
                firefoxBinary.addCommandLineOptions("--headless");
                firefoxBinary.addCommandLineOptions(WINDOW_SIZE);
                FirefoxOptions firefoxOptions = new FirefoxOptions();
                firefoxOptions.setBinary(firefoxBinary);
                WebDriverManager.firefoxdriver().setup();
                return new FirefoxDriver(firefoxOptions);
            case IE:
                WebDriverManager.iedriver().setup();
                return new InternetExplorerDriver();
            case EDGE:
                WebDriverManager.edgedriver().setup();
                return new EdgeDriver();
            case SAFARI:
                driver = new SafariDriver();
                return new SafariDriver();
            default:
                WebDriverManager.chromedriver().setup();
                return new ChromeDriver();
        }
    }
}

Here is my BasePage:

package common;

import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.PageFactory;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
import util.driver.Driver;
import java.util.logging.Logger;


public abstract class BasePage {

    protected static String BASE_URL = System.getenv("base_URL");
    protected static final Logger log = Logger.getLogger(BasePage.class.getName());
    private WebDriver driver = Driver.driver;


    public BasePage() {

        PageFactory.initElements(driver, this);

    }

    protected void waitForElementClickable(WebElement element){
        WebDriverWait wait = new WebDriverWait(driver, 30);
        wait.until(ExpectedConditions.elementToBeClickable(element));
    }

    protected void waitForElementVisible(WebElement element){
        WebDriverWait wait = new WebDriverWait(driver, 15);
        wait.until(ExpectedConditions.visibilityOf(element));
    }

    protected void setTextAs(WebElement element, String text){
        waitForElementClickable(element);
        element.sendKeys(text);
    }

    protected void clearElement(WebElement element){
        waitForElementClickable(element);
        element.clear();
    }

    protected void clickElement(WebElement element){
        waitForElementClickable(element);
        element.click();
    }

    protected void clickElementByJavascriptExecutor(String xpath){
        WebElement element=driver.findElement(By.xpath(xpath));
        JavascriptExecutor ex=(JavascriptExecutor)driver;
        ex.executeScript("arguments[0].click()", element);
    }

    protected void clickLink(WebElement element){
        waitForElementVisible(element);
        element.click();
    }

    protected String getText(WebElement element){
        waitForElementVisible(element);
        return element.getText();
    }

    protected void freeze(int seconds) {
        try {
            Thread.sleep(seconds * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

This is my stepdefinition class Step_First:

package steps;

import common.BasePage;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
import pages.Page_First;
import util.driver.Driver;

import java.io.IOException;


public class Step_First extends BasePage {

    private WebDriver driver = Driver.driver;
    private Page_First page_first = PageFactory.initElements(driver, Page_First.class);


    @Given("I go to Google")
    public void I_go_to_Googl () {

        page_first.navigateToBrowser();
    }

    @When("I query for {string} cucumber spring selenium")
    public void I_query_for_cucumber_spring_selenium (String search) throws IOException {

        page_first.search(search);
    }

    @When("click search")
    public void click_search(){

        page_first.enterButton();
    }

    @Then("google page title should become the first page")
    public void google_page_title_should_become_the_first_page() {

        log.info("All OK");
    }

}

This is my Runner file TestRunner

package runner;

import org.junit.runner.RunWith;
import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;

@RunWith(Cucumber.class)
@CucumberOptions(
        features = "src/test/java/features",
        glue= {"steps"},
        monochrome = true,
        plugin = {"pretty", "html:TestReports", "json:TestReports/cucumber.json", "junit:TestReports/cucumber.xml"}
)

public class TestRunner {
}

Below, my feature file fist.feature

Feature: Navigation Test

  Scenario: Search google.com to verify google search is working

    Given I go to Google
    When I query for "<search>" cucumber spring selenium
    And click search
    Then google page title should become the first page

I have my config file default.properties

# default.properties
# properties set here will be available to the test execution as environment variables

# Browser
browser = firefox

# Base URL
base_URL = https://www.google.com

# Search
search = cucumber selenium

And don't foget about my POM:

<?xml version="1.0" encoding="UTF-8"?>
<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>automation</groupId>
    <artifactId>maven_selenium_cucumber</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.version>3.7.0</maven.compiler.version>
        <cucumber.version>3.0.2</cucumber.version>
        <selenium.version>3.12.0</selenium.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-jvm-deps</artifactId>
            <version>1.0.6</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-core</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-java8 -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-java8</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.cucumber/cucumber-picocontainer -->
        <dependency>
            <groupId>io.cucumber</groupId>
            <artifactId>cucumber-picocontainer</artifactId>
            <version>${cucumber.version}</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>${selenium.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/io.github.bonigarcia/webdrivermanager -->
        <dependency>
            <groupId>io.github.bonigarcia</groupId>
            <artifactId>webdrivermanager</artifactId>
            <version>3.7.1</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.5</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

The issues here are 2:

1.- I wrote in my config file (default.properties) the option firefox in browser, but the navigator is opening Chrome.

2.- After some seconds, the browser crashes and console displays the next error message:

java.lang.NullPointerException: null value in entry: url=null
    at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:32)
    at com.google.common.collect.SingletonImmutableBiMap.<init>(SingletonImmutableBiMap.java:42)
    at com.google.common.collect.ImmutableBiMap.of(ImmutableBiMap.java:70)
    at com.google.common.collect.ImmutableMap.of(ImmutableMap.java:123)
    at org.openqa.selenium.remote.RemoteWebDriver.get(RemoteWebDriver.java:271)
    at pages.Page_First.navigateToBrowser(Page_First.java:37)
    at steps.Step_First.I_go_to_Google(Step_First.java:24)
    at ✽.I go to Google (/Users/rodrigo.g/Documents/automation_projects/maven_selenium_cucumber/src/test/java/features/first.feature:8)


Skipped step

Skipped step

Skipped step
Feb 21, 2020 7:18:03 PM util.driver.Driver closeDriver
INFO: $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ Finish of Test Execution $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Feb 21, 2020 7:18:03 PM util.driver.Driver closeDriver
INFO: Driver closed

Failed scenarios:
/Users/rodrigo.g/Documents/automation_projects/maven_selenium_cucumber/src/test/java/features/first.feature:6 # Search google.com to verify google search is working

1 Scenarios (1 failed)
4 Steps (1 failed, 3 skipped)
0m2.833s

java.lang.NullPointerException: null value in entry: url=null
    at com.google.common.collect.CollectPreconditions.checkEntryNotNull(CollectPreconditions.java:32)
    at com.google.common.collect.SingletonImmutableBiMap.<init>(SingletonImmutableBiMap.java:42)
    at com.google.common.collect.ImmutableBiMap.of(ImmutableBiMap.java:70)
    at com.google.common.collect.ImmutableMap.of(ImmutableMap.java:123)
    at org.openqa.selenium.remote.RemoteWebDriver.get(RemoteWebDriver.java:271)
    at pages.Page_First.navigateToBrowser(Page_First.java:37)
    at steps.Step_First.I_go_to_Google(Step_First.java:24)
    at ✽.I go to Google (/Users/rodrigo.g/Documents/automation_projects/maven_selenium_cucumber/src/test/java/features/first.feature:8)


Process finished with exit code 1

Please, somebody could help me with these 2 issues?


Answer:

Firstly, there is a lot of useless info. Also, I would invite you to take a look on this part of your code:

Your Driver.class:

driver = DriverFactory.getDriver();

You trying to initialize it for the first time for further using. Then:

if (BROWSER == null) {
            WebDriverManager.chromedriver().setup();
            return new ChromeDriver();
        }

So you're saying get me Chrome if there is no active browser. Also, in your DriveFactory.class in switch:

default:
        WebDriverManager.chromedriver().setup();
        return new ChromeDriver();

So you're saying get me Chrome by default That's the probable reason of Chrome invocation instead of FF.

Regarding NPE, I didn't find the line in your code on how you define the path to your .properties file. BTW, how this line should work?

protected static String BASE_URL = System.getenv("base_URL");

I would recommend you to use the Properties class to define it. Smth like this below.

Properties properties = new Properties();
  properties.load(new FileInputStream("yourPropertiesFilePath"));
  String browserName = properties.getProperty("base_URL");

Hope this will help.

Question:

Cucumber: how can you create a BaseSteps class if you can’t use inheritance with Cucumber?

Login Steps inherits the CommonSteps class:

    public class LoginSteps extends CommonSteps {

    WebDriver driver = getDriver();

    @Given("^User navigates to the \"([^\"]*)\" website$")
    public void user_navigates_to_the_website(String url) throws Throwable {
        basePage.loadUrl(url);
    }

    @And("^User entered the \"([^\"]*)\" username$")
    public void user_entered_the_username(String username) throws Throwable {
        loginPage.setUsername(username);
    }






public class CommonSteps  {
    @After
    public void close_browser_window(Scenario scenario) throws Exception {
        if (scenario.isFailed()) {
            scenario.embed(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES), "image/png");
        }
    }
}

Answer:

You can use inheritance, just not with steps for the reason's cited in Roberto Pegoraro's link. I like to organize my steps into different step def files. But this leads to interoperability problems. If you use class variables to communicate between steps then those steps have to be in the same file; unless you use inheritance. I create a UiCommon class to contain the shared class variables (e.g. page file instance variables) that the steps use to communicate between themselves. Each step definition file extends UiCommon. Now it doesn't matter how I refactor the steps definitions between the various step definition files. They can still communicate.

For small projects this isn't usually an issue. But for a large project with multiple test automation engineers who need to minimize git merge conflicts it matters.

Question:

I'm trying to do automation at work through selenium webdriver using Eclipse and cucumber. I'm getting the below error while running my feature files

java.lang.Error: Unresolved compilation problem: driver cannot be resolved

As you can see below, in my Tests_Steps.java class I have declared the variable "driver" correctly. I have also assigned the object to the instance of a class(FirefoxDriver). Below is my code.

package stepDefinition;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class Tests_Steps {

@Given("^User is on the Home Page$")
    public void user_is_on_the_Home_Page() throws Throwable {
        WebDriver driver=new FirefoxDriver();
        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
        driver.get("http://www.gmail.com/login");
    }

    @When("^User Clicks on the Login$")
    public void user_Clicks_on_the_Login() throws Throwable {
        driver.findElement(By.xpath(".//*[@id='login']")).click();
    }

    @When("^User enters UserName and Password$")
    public void user_enters_UserName_and_Password() throws Throwable {
        driver.findElement(By.id("login")).sendKeys("ab24146_111");
        driver.findElement(By.id("psw")).sendKeys("Password1");
        driver.findElement(By.id("loginButton")).click();
    }

    @Then("^Message displayed LogIn Successfully$")
    public void message_displayed_LogIn_Successfully() throws Throwable {
        System.out.println("Login Successfully");
    }

For some reason my driver variable is not being recognized on the second and the third step. I see red squiggly lines and when I hover my mouse on the red line it says "driver cannot be resolved" In the first step its working fine.

Can you guys please help me in what needs to be done.


Answer:

java.lang.Error: Unresolved compilation problem: driver cannot be resolved

Actually you're declaring WebDriver variable inside user_is_on_the_Home_Page() locally, so this is limited and and would be available only for this method.

You should declare this variable globally which would be available for all of those methods as below :-

public class Tests_Steps {

  WebDriver driver = null;

  @Given("^User is on the Home Page$")
  public void user_is_on_the_Home_Page() throws Throwable {
    driver=new FirefoxDriver();
    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    driver.get("http://www.gmail.com/login");
  }

  ------------
  ------------
}

Question:

Currently the following command would work when attempting to run tests via the command line window however since updating to io.cucumber from info.cakes it no longer seems to work?

mvn test -Dcucumber.options="--tags @login"

Exception message:

Sep 17, 2019 5:18:37 PM cucumber.runtime.FeaturePathFeatureSupplier get
WARNING: No features found at classpath:runners

However running tests directly from the runner class works:

package runners;

import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.Cucumber;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)

@CucumberOptions(features = { "classpath:features" }, glue = {
        "stepDefinitions"}, monochrome = true, tags = {"@login"}, dryRun = false,
        plugin = { "pretty", "html:target/cucumber", "json:target/cucumber.json"})

    public class MainRunner extends AbstractTestNGCucumberTests {
}

Cucumber version:

<cucumber.version>4.7.2</cucumber.version>

Answer:

import io.cucumber.junit.CucumberOptions;
import io.cucumber.junit.Cucumber;
import io.cucumber.testng.AbstractTestNGCucumberTests;
import org.junit.runner.RunWith;

You are mixing JUnit and TestNG. You should in a single class use either JUnit or TestNG. Not both.

Question:

I have a design issue when I am trying to build a framework using cucumber, selenium and cucumber-spring. My expected behavior is to quit WebdDriver instance for every scenario. But

Here is my page objects in src\main\java

@Component
public class BasePage {
WebDriver driver;
 public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(driver, this);

 }
 public WebDriver getDriver() {
    return this.driver;
  }

}

Here is another page object class which extends the Base class.

@Component
public class LoginPage extends BasePage
{
public LoginPage(WebDriver webDriver) {
    super(webDriver);
}

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[1]")
WebElement loginTextBox;

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[2]")
WebElement passwordTextBox;

@FindBy(xpath="/html/body/app-root/s-login-pg/div/form/button")
WebElement loginButton;

public void openApplication(String url){
    driver.get(url);
    waitForPageToLoad();
}

public void inputUsername(String username){
    loginTextBox.sendKeys(username);
}

public void inputPassword(String password){
    loginTextBox.sendKeys(password);
}

public void clickLoginButton(){
    loginButton.click();
 }
}

The webdriver is created with Factory Design pattern. Based on the browser mentioned in the properties file it will create the desired webdriver instance. And these Driver classes are not created with @Component

And spring configuration class under src/test/java as shown below.

@Configuration
@ContextConfiguration(classes={PropertiesContext.class})
@ComponentScan(basePackages = "com.company.project")
public class CucumberContext {

@Autowired
private String browser;

  @Bean(name = "webdriver", destroyMethod = "quit")
  public WebDriver getWebDriver() {
    WebDriver webdriver = null;
    webdriver = DriverManagerFactory.getManager(browser).getDriver();
    return webdriver;
  }
}

This is the step definitions class under src\test\java

public class StepDefinitions extends ParentSteps {

@Autowired
private LoginPage loginPage;

@Autowired
private HomePage homePage;

@Before
public void init() {
    if (System.getProperty("environment") == null) {
        System.setProperty("environment", "DEV");
    }
}

@After
public void tearDown(Scenario scenario) {
    if(loginPage.getDriver() != null) {
        loginPage.getDriver().quit;
    }
}

}

Here is my actual problem in the Step Definitions. For every Test Scenario If I call driver.quit() the remaining test scenarios will be failed with the below exception because the bean WebDriver killed in @After

org.openqa.selenium.NoSuchSessionException: Session ID is null. Using WebDriver after calling quit()?
Build info: version: '3.14.0', revision: 'aacccce0', time: '2018-08-02T20:19:58.91Z'
Driver info: driver.version: RemoteWebDriver

at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:125)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:548)

The reason why I am getting this error is because the webdriver is closed which is an Injected bean. Is there any solution to create wedriver in @Before and kill webdriver in @After for each cucumber scenario? Is there any flaw in the design?


Answer:

Apart from the @DirtiesContext used by OP as solution . Tried using @Scope(SCOPE_CUCUMBER_GLUE)/@Scope("cucumber-glue") . Unique instance of Webdriver is created and destroyed in each scenario.

Reference

Changing a Spring bean's scope to SCOPE_CUCUMBER_GLUE will bound its lifecycle to the standard glue lifecycle.

import org.springframework.stereotype.Component;
import org.springframework.context.annotation.Scope;
import static io.cucumber.spring.CucumberTestContext.SCOPE_CUCUMBER_GLUE;

@Component
@Scope(SCOPE_CUCUMBER_GLUE)
public class MyComponent {
}

Base Page:

@Component
@Scope("cucumber-glue")
public class BasePage {
WebDriver driver;
 public BasePage(WebDriver driver) {
    this.driver = driver;
    PageFactory.initElements(driver, this);

 }
 public WebDriver getDriver() {
    return this.driver;
  }

}

Base Page :

@Component
@Scope("cucumber-glue")
public class LoginPage extends BasePage
{
public LoginPage(WebDriver webDriver) {
    super(webDriver);
}

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[1]")
WebElement loginTextBox;

@FindBy(xpath = "/html/body/app-root/s-login-pg/div/form/input[2]")
WebElement passwordTextBox;

@FindBy(xpath="/html/body/app-root/s-login-pg/div/form/button")
WebElement loginButton;

public void openApplication(String url){
    driver.get(url);
   // waitForPageToLoad();
}

public void inputUsername(String username){
    loginTextBox.sendKeys(username);
}

public void inputPassword(String password){
    loginTextBox.sendKeys(password);
}

public void clickLoginButton(){
    loginButton.click();
 }
}

Configuration:

@Configuration
// Not define in example so commented @ContextConfiguration(classes= 
//{PropertiesContext.class})
@ComponentScan(basePackages = "com.company.project")
public class CucumberContext {

@Autowired
private String browser;

  @Bean(name = "webdriver", destroyMethod = "quit")
  @Scope("cucumber-glue")
  public WebDriver getWebDriver() {
      WebDriver webdriver = null;
      // Removed the factory initialization code. Used simple ChromeDriver
      webdriver = new ChromeDriver();
      return webdriver;
  }
}

Steps:

public class StepDefinitions extends ParentSteps {

@Autowired
private LoginPage loginPage;

@Autowired
private HomePage homePage;

@Before
public void init() {
    if (System.getProperty("environment") == null) {
        System.setProperty("environment", "DEV");
    }
}

@After
public void tearDown(Scenario scenario) {
   // Removed quit
   // if(loginPage.getDriver() != null) {
   //     loginPage.getDriver().quit;
  //   }
}
}

Note: All chromeriver background processes are killed.

Question:

I would like to know how to find all the elements in the same page and assert them they are displayed in the page using Data table in Selenium / Java /Cucumber.

For example, I have a scenario like this

Sceanario: Verify all the elements in the xyz page
Given I am in the abc page
When I navigate to xyz page
Then I can see the following fields in the xyz page
|field 1|
|field 2|
|field 3|
|field 4|

Answer:

First Step : Constructing Data Table. (Clue, Using Header we can implement Data Table in much clean & precise way and considering Data Table looks like below one)

Then I can see the following fields in the xyz page
    | Field Name | Locator |
    |  field 1   |  Xpath1 |
    |  field 2   |  Xpath2 |
    |  field 3   |  Xpath3 | 
    |  field 4   |  Xpath4 | 

Second Step : Implementing Step Definition

    @Then    
    public void I_can_see_the_following_fields_in_the_xyz_page(DataTable table) throws Throwable {
        WebElement element;
        List<Map<String, String>> list = table.asMaps(String.class,String.class); 
        for(Map<String, String> list : data) {
            element = driver.findElement(By.xpath(list.get("Locator")));
            Assert.assertTrue("Element : "+list.get("Field Name")+ "not found",isElementPresent(element));   
        }
    }

Utility Method : To check if element present

    protected synchronized boolean isElementPresent(WebElement element) {
        boolean elementPresenceCheck = false;
        Wait<WebDriver> wait=null;
        try {
            wait = new FluentWait<WebDriver>((WebDriver) driver).withTimeout(10, TimeUnit.SECONDS).pollingEvery(1,
                    TimeUnit.SECONDS);
            elementPresenceCheck = wait.until(ExpectedConditions.visibilityOf(element)).isDisplayed();
            return elementPresenceCheck;
        }catch(Exception e) {
            return elementPresenceCheck;
        }
    }

Question:

During a test automation journey i am running, i need to verify an email address which must be different each time. Instead of using multiple different email address's, we have set up an office 365 account that allows +(number) ie test+1@test.com. Although i know how to create an increment by 1 method i am unsure of how to incorporate that into the email address within a method to give me a different email each time. Apologies if this is already in stack overflow but i couldn't find it. Thanks


Answer:

You can use a dedicated gmail account and before using it you can append +timestamp in it. example: let's say you have a account on gmail ABC@gmail.com Now, every time you use this email for verification append ABC+timestamp@gmail.com this email is new for you application but you will always receive verification code on ABC@gmail. you can read ABC@gmail every time for the latest mail for verification. I have used this methods and it works fine with gmail.

Try to test it manually make and gmail account with any name say Mdug@gmail.com Now send email to Mdug+1@gmail.com using different account. you will receive mail at Mdug@gmail.com because in gmail Mdug+anything@gmail.com == Mdug@gmail.com.

Every time you have to read latest mail in Mdug@gmail.com because every verification code will go there

Instead of using random number you can append (Epoch)timestamp after + in email id because it will always be unique

Question:

I've got a list of webelements and I need to write every element form the list in separate cell in Excel. Currently when for example i have 2 elements in a list, second one deletes first element in cell.

    List<WebElement> products = driver.findElements(By.xpath("//label[contains(text(),'Size')]"));
    for (WebElement product:products){
        SetCellData(product.getText(),1,0);

Answer:

so it depends on how you want the data. i'm guessing you are using apache poi. or something similar your loop doesn't move around the workbook it just writes to the same cell here is a example i pulled from a tutorial

 //This data needs to be written (Object[])
    Map< String, Object[] > empinfo =
            new TreeMap<>();
    empinfo.put( "1", new Object[] { "EMP ID", "EMP NAME", "DESIGNATION" });
    empinfo.put( "2", new Object[] { "tp01", "Gopal", "Technical Manager" });
    empinfo.put( "3", new Object[] { "tp02", "Manisha", "Proof Reader" });
    empinfo.put( "4", new Object[] { "tp03", "Masthan", "Technical Writer" });
    empinfo.put( "5", new Object[] { "tp04", "Satish", "Technical Writer" });
    empinfo.put( "6", new Object[] { "tp05", "Krishna", "6546984651685465132198651324984351" });

    //Iterate over data and write to sheet
    Set< String > keyid = empinfo.keySet();
    int rowid = 0;

    for (String key : keyid) {
        row = spreadsheet.createRow(rowid++);
        Object [] objectArr = empinfo.get(key);
        int cellid = 0;

        for (Object obj : objectArr) {
            Cell cell = row.createCell(cellid++);
            cell.setCellValue((String)obj);
        }
    }

so if you want each element in 1 row. you will do Cell cellToFill = row.createCell(nextCellColNumber)

if you want a vertical list it'll be create Row create cell(0) and set value there

Question:

I'm trying to open different types of files using webdriver(.txt and pdf). So I have the files in the resources folder but when I open them I get the following error message: malformed exception

But if I open the file from my desktop it works perfectly fine:

So for example this is what I have:

 String file_loc = logInPage.getFile(file_name);
    logInPage.navigateToFileLoc(file_location);

These are the implementation of the two methods

 public String getFile(String fileName) {

        String result = "";

        ClassLoader classLoader = getClass().getClassLoader();
        try {
            result = IOUtils.toString(classLoader.getResourceAsStream(fileName), java.nio.charset.StandardCharsets.UTF_8);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

public void navigateToFileLoc(String fileLoc){
   webDriver.get(fileLoc);
}

But when I try to get the file from the desktop it works perfectly fine: For example webDriver.get("file:///C:/Users/test.pdf")

It's like as if you are trying to open a pdf or html in an IDE


Answer:

Can you please change the getFile method as follow :

public String getFile(String fileName) {
        String filePath = null;
        ClassLoader classLoader = getClass().getClassLoader();
        try {
            filePath= classLoader.getResource(fileName).getPath();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  "file://"+filePath;
    }

Question:

How to create a MasterStep / BaseStep if the my sub step files already extend a class?

Example code for one of my steps files:

public class LoginSteps extends DriverFactory {

WebDriver driver = getDriver();

@Given("^User navigates to the \"([^\"]*)\" website$")
public void user_navigates_to_the_website(String url) throws Throwable {
    basePage.loadUrl(url);
}

@And("^User entered the \"([^\"]*)\" username$")
public void user_entered_the_username(String username) throws Throwable {
    loginPage.setUsername(username);
}

@And("^User entered the \"([^\"]*)\" password$")
public void user_entered_the_password(String password) throws Throwable {
    l

I need to use the following tags/ code below but i dont want to repeat within every step class / file and when trying to add the cucumber tags inside my DriverFactory im not allowed to because Cucumber dosnt allow you to add tags inside extended classes.

    @After
public void close_browser_window(Scenario scenario) throws Exception {
    if (scenario.isFailed()) {
        scenario.embed(((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES), "image/png");
    }
}

Thanks for your help


Answer:

Create BaseSteps which extends DriverFactory, then your LoginSteps extends BaseSteps:

public class BaseSteps extends DriverFactory {

     WebDriver driver = getDriver();

     @After
     public void close_browser_window(Scenario scenario) throws Exception {
      if (scenario.isFailed()) {
       scenario.embed(((TakesScreenshot) 
       driver).getScreenshotAs(OutputType.BYTES), "image/png");
}

}

Question:

How can i change between browsers when i run a specific scenario in Java?

I already imported the 2 browsers so far i can only open both of them using the code

public void accessURL() throws Throwable
{

    Registration_Steps_1.setUp();
    for(String browser : browserDriver)
    {

        driver=Registration_Steps_1.initiateBrowserDriver(browser);
        //driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
        driver.get(baseUrl);    
        super.driver = driver;

    }

}

after that i cannot run the other methods for each of the browsers


Answer:

Do you want to run test on both browser if yes, user testng suite and pass browser parameter from testng suite.

Second approach setup browser type in configuration file read from there and run test on browser as mention in configuration file.

Question:

My Cucumber feature looks like this: Feature: Login Action

Scenario: Successful Login with Valid Credentials
Given User is on Home Page
When User Navigate to LogIn Page
And User enters UserName and Password
Then Message displayed Login Successfully

Scenario: Successful LogOut
When User LogOut from the Application
Then Message displayed LogOut Successfully

When I run it, I get the following error:

WARNING: Cucumber-JVM's --format option is deprecated. Please use --plugin instead. Exception in thread "main" java.lang.IllegalArgumentException: Not a file or directory: C:\Users\testjack001\workspace\myProject\src\myFeature.feature at cucumber.runtime.io.FileResourceIterator$FileIterator.(FileResourceIterator.java:54) at cucumber.runtime.io.FileResourceIterator.(FileResourceIterator.java:20) at cucumber.runtime.io.FileResourceIterable.iterator(FileResourceIterable.java:19) at cucumber.runtime.model.CucumberFeature.loadFromFeaturePath(CucumberFeature.java:101) at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:54) at cucumber.runtime.model.CucumberFeature.load(CucumberFeature.java:34) at cucumber.runtime.RuntimeOptions.cucumberFeatures(RuntimeOptions.java:201) at cucumber.runtime.Runtime.run(Runtime.java:109) at cucumber.api.cli.Main.run(Main.java:36) at cucumber.api.cli.Main.main(Main.java:18)

How can I get this issue resolved?


Answer:

The entry regarding the --format option is just a warning, it is not an error. Your error starts in the next line:

Exception in thread "main" java.lang.IllegalArgumentException: Not a file or directory: C:\Users\testjack001\workspace\myProject\src\myFeature.feature

Cucumber can not find your feature file at the location it expects it to be placed.

Question:

I use Selenium Webdriver tests based on Java/Gherkin/Cucumber.

I have a test running that I want to run multiple times, without me having to restart the scenario several times.

The Gherkin script is something like this:

Given the user opens a browser
Then the user fills in the form
Then the user repeats the filling of the form *5* times 

This way, if I want 10 forms to be filled in, I can just replace the 5 with 10, press play, and grab a beer.

Is this at all possible or do I just have to re-run the scenario manually 5 times?


Answer:

First you could simplify a bit your Gherkin scenario, like:

 Given the user opens a browser

 Then the user fills in the form 5 times

Taking this scenario you then generate your methods and in the second method you can add a loop, like:

[Then(@"the user fills in the form (.*) times")]

public void ThenTheUserFillsInTheForm(int nrOfTimes)   
{        
    for(int i = 0; i < nrOfTimes; i++)
    {

      //user fills in the form

    }
} 

Question:

I am unable to set parameters through cucumber feature file as TestNG throws error because of the Parameter conflict

"Cannot inject @Test annotated Method [days_of_the_week_is_enabled_by_default] with [class java.lang.String, class java.lang.String]" 

As you see from the below code snippet, I am using cucumber's feature file to pass the parameter to the method but when I add the testNG annotation @Test, It throws me an error as cannot inject @Test.

I am aware how to use Parameters in TestNG but I want the Parameters to be taken from Feature file instead of TestNG Parameters. Anyway we could accomplish this ?

@Test
@Then("^(.*) is (.*) by default$")
public void days_of_the_week_is_enabled_by_default(String dOWeek, String status) {
        draftPage.daysSelectionDefault(dOWeek, status);
    }

Answer:

That cannot be done. You can make use of TestNG as a runner to run your cucumber based tests. But that would perhaps lead to TestNG creating one @Test method which runs all the feature files. You can replace TestNG and use JUnit for the same too.

You would need to employ other mechanisms such as JVM arguments perhaps to pass parameters to your cucumber tests.

The other option would be for you to build a TestNG listener, and from it get hold of the ITestContext and through the test context, you can extract out the parameters.

//This class is not thread safe, and will give unpredictable results
//if you multiple <test> tags running.
import org.testng.ITestContext;
import org.testng.ITestListener;

public class LocalListener implements ITestListener {

  private static LocalListener instance;
  private ITestContext testContext;

  private static void setInstance(LocalListener obj) {
    instance = obj;
  }

  public static LocalListener getInstance() {
    return instance;
  }

  public LocalListener() {
    setInstance(this);
  }

  @Override
  public void onStart(ITestContext context) {
    this.testContext = context;
  }

  public ITestContext getTestContext() {
    return testContext;
  }
}

Question:

public class MyDriverManager {
private WebDriver webdriver;
@BeforeClass
public static void beforeClass()
{
    WebDriverManager.chromedriver().setup();
    WebDriverManager.firefoxdriver().setup();
    WebDriverManager.edgedriver().setup();
}
@BeforeMethod
public void beforeMethod()
{
    webdriver=new ChromeDriver();
    webdriver.manage().window().maximize();
}
@AfterMethod
public  void AfterMethod()
{
    webdriver.close();
}
@Test
public  void test()
{
    webdriver.get("http://www.google.com/");
}

}

On running @Test, I am getting java.lang.NullPointerException as an error, Anyone, please let me know where I have committed the mistake. Also, is there any feasible way to use it in the framework so that I can access my feature file? I tried it using in the RunnerClass but doesn't seem to be the right way to proceed.


Answer:

When you directly run your @Test, I'm assuming you are using some IDE and right clicking on the @Test annotation and running it. If thats the case, chances are that your @BeforeMethod is not getting called, hence WebDriver is coming up as null

To verify this, you can debug or put some kind of print statement to check.

Use below code to verify the error if you are NOT DEBUGGING (just modified your code)

public class MyDriverManager {
private WebDriver webdriver;
@BeforeClass
public static void beforeClass()
{
    WebDriverManager.chromedriver().setup();
    WebDriverManager.firefoxdriver().setup();
    WebDriverManager.edgedriver().setup();
}
@BeforeMethod
public void beforeMethod()
{
    System.out.println( " control is inside beforeMethod now");
    webdriver=new ChromeDriver();
    webdriver.manage().window().maximize();
}
@AfterMethod
public  void AfterMethod()
{
    webdriver.close();
}
@Test
public  void test()
{
    System.out.println( " control is inside test method now");
    webdriver.get("http://www.google.com/");
}

}

Question:

In eclipse IDE, I have created a basic cucumber framework by using Maven project.

I have added all the dependencies required in pom.xml.For TestNG plugin added below dependencies.

 <dependency>       
      <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>              
        <version>6.14.3</version>
        <scope>test</scope>         
</dependency> 
<dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-testng</artifactId>
        <version>1.2.5</version>   
 </dependency>

But 'TestNG Suite' option was not coming in preferences,so installed TestNG through Help->Install New Software.

Framework is having feature file(scenario is described),stepdefinitions(code/logic given) and runner class(To map feature with stepdefinitions file and run it).

Runner class :

package tests.report.runners;

import cucumber.api.CucumberOptions;


@CucumberOptions(features = "src/test/resources/features",glue= {"tests"},tags= {"@Report"})
public class ReportRunner  {
    }

Like this I have one runner class for each module(End to End scenario)

Ex :

  • Login, go to product page and logout

  • Login,generate report and logout

I am trying to run these runner class by testng.xml file

testng.xml file

 <?xml version="1.0" encoding="UTF-8"?> 
 <!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
   <suite name="First Suite" parallel="classes"> 
    <test name="Chrome Test" parallel="classes">
       <classes> 
           <class name ="tests.report.runners.ReportRunner"></class>
       </classes> 
   </test> 
</suite>

But its throwing below error


Answer:

Issue was because of incompatible junk jars stored in maven repositeries.

Please follow below steps

  1. Clean old properties/maven dependencies(Open command prompt from yours project directory and run below commands)
    • mvn eclipse:clean
    • mvn eclipse:eclipse -Dwtpversion=2.0
  2. Download below cucumber jar files and add in your project(don't add it in pom directly)

    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-core</artifactId>
        <version>1.2.5</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>1.2.5</version>
    </dependency
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-jvm-deps</artifactId>
        <version>1.0.5</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>gherkin</artifactId>
        <version>2.12.2</version>
        <scope>provided</scope>
    </dependency>
    
  3. Make sure that You have already TestNG library into project

  4. Add below cucumber-testng dependencies in pom.xml file

    <dependency>
       <groupId>info.cukes</groupId>
       <artifactId>cucumber-testng</artifactId>
       <version>1.2.5</version>
    </dependency>
    
  5. Extend runner class with AbstractTestNGCucumberTests

  package tests.report.runners;
  import org.testng.annotations.Test;
  import cucumber.api.testng.AbstractTestNGCucumberTests;
  import cucumber.api.CucumberOptions;
  @Test
  @CucumberOptions(features = "src/test/resources/features",glue= {"tests"},tags= 
  {"@Report"})
  public class ReportRunner extends AbstractTestNGCucumberTests {
  }
  1. Execute with below testng.xml file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="First Suite" >
<test name="Chrome Test" >
<classes>
<class name ="tests.report.runners.ReportRunner"></class>
</classes> 
</test>
</suite>

Thanks!

Question:

I'm using cucumber and selenium.

I have three .feature files:

1)auth.feature

2)registration.feature

3)userInformation.feature

I have individual step definitons classes for them

1)authSteps.class

2)registrationSteps.class

3)userInformationSteps.class

IN each class I create webdriver like this

WebDriver driver = new WebDriver(ChromeDriver);

When I run the tests,all driver starts together,even if I have tagged test case and only run 1 case,the webdrivers are started too. @before doesn't work.

I want only to run the feature's webdriver. All if I test all features, I want to run the webdrivers in linear ways.


Answer:

1.Create one AbstractHook class in TestScript package

public class AbstractHook {
protected static WebDriver driver;

    protected WebDriver getdriver() {
        if (driver == null) {
        System.setProperty("webdriver.gecko.driver","geckodriver.exe");
            driver = new FirefoxDriver();

        } else if (driver == null) {

            System.setProperty("webdriver.chrome.driver",
                "chromedriver.exe");
            driver = new ChromeDriver();

        } 
        return driver;
    }

2.Hook class

public class Hook extends AbstractHook {

    AbstractHook df = new AbstractHook();

    @Before
    public void createdriver() {
        df.getdriver();
        driver.get("some url");// no need 

    }
}

3.TestScript code

    public class TestScript01 extends AbstractHook {
        WebDriver driver = getdriver();

        @Given("^I want to open the gmail url on firefox$")
        public void i_want_to_open_the_Gmail_url_on_firefox() throws Throwable {

            driver.get("give some url");
        }
}

4.Runner class

@RunWith(Cucumber.class)
@CucumberOptions(features = "Feature", monochrome = true, glue = { "com.scripts" }, plugin = { "pretty","html:target/cucumber" },
         tags = {"@sa,@sanity" },
        // dryRun = false)
public class RunnerClass {

}

Try in this way, The driver will be initialized once and used in all the TestScript classes .

Question:

I'm facing the next issue working with Cucumber in Maven project. This is because I don't have a Runnable method for do this. I was looking for information about, but it has been hard for me.

java.lang.Exception: No runnable methods

    at org.junit.runners.BlockJUnit4ClassRunner.validateInstanceMethods(BlockJUnit4ClassRunner.java:191)
    at org.junit.runners.BlockJUnit4ClassRunner.collectInitializationErrors(BlockJUnit4ClassRunner.java:128)
    at org.junit.runners.ParentRunner.validate(ParentRunner.java:416)
    at org.junit.runners.ParentRunner.<init>(ParentRunner.java:84)
    at org.junit.runners.BlockJUnit4ClassRunner.<init>(BlockJUnit4ClassRunner.java:65)
    at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParameters.<init>(BlockJUnit4ClassRunnerWithParameters.java:27)
    at org.junit.runners.parameterized.BlockJUnit4ClassRunnerWithParametersFactory.createRunnerForTestWithParameters(BlockJUnit4ClassRunnerWithParametersFactory.java:16)
    at org.junit.runners.Parameterized.createRunnersForParameters(Parameterized.java:313)
    at org.junit.runners.Parameterized.<init>(Parameterized.java:248)
    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)

This is my Runner Cucumber Class:

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
import org.junit.runner.RunWith;

@RunWith(Cucumber.class)
@CucumberOptions(features={"src/features/Login.feature"}
                 ,format = {"pretty", "html:target/cucumber"}
                 ,glue = {"cucumber.CucumberStepDefs"}
)
/*@Suite.SuiteClasses({
        CucumberStepDefs.class,
})*/

public class CucumberRunnerTest {
}

This is my Selenium/cucumber class:

import cl.chipacorp.test.SolutAutomatedWebTest;
import cl.chipacorp.util.data.SetDatos;
import cl.chipacorp.util.report.Report;
import cucumber.annotation.en.Given;
import cucumber.annotation.en.Then;
import cucumber.annotation.en.When;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.openqa.selenium.By;
import org.openqa.selenium.ie.InternetExplorerDriver;

import java.util.concurrent.TimeUnit;

//JAVA

@RunWith(value = Parameterized.class)
public class CucumberStepDefs extends CoopeuchAutomatedWebTest {


    @Parameterized.Parameter(value = 0)
    public String usuario;
    @Parameterized.Parameter(value = 1)
    public String pass;


    @Parameterized.Parameters
    public static Object[] data() {
        return SetDatos.getInstance().getData(CucumberStepDefs.class);
    }


    @Given("^Ingresar a la URL de Branch en ambiente QA$")
    public void Login() throws Exception {


        driver = new InternetExplorerDriver();
        driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
        baseUrl = "http://brs1coreqa-01.coopeuch1.cl/";
        driver.get(baseUrl + "IBSBranchnet_COOPEUCH_Q5A/WebTeller.htm");
        driver.switchTo ().defaultContent ();
        driver.switchTo ().frame ("frmbody");
    }


    @When("^Se desplieguen los campos Username y Password, Ingresar las credenciales correspondientes$")
    public void UsuarioPass () throws Exception {

        driver.findElement(By.id("TxbTELLUSERID")).clear();
        driver.findElement(By.id("TxbTELLUSERID")).sendKeys(usuario);
        driver.findElement(By.id("TxbUSERPASSW")).clear();
        driver.findElement(By.id("TxbUSERPASSW")).sendKeys(pass);

        screenshot.take (this, driver, "LoginR C01");

        driver.findElement(By.id("BtnSubmit")).click();
    }

    @Then("^Usuario accede a Branch con su correspondiente usuario$")
    public void Logout () throws Exception {
        driver.switchTo ().defaultContent ();
        driver.switchTo ().frame ("frmwebteller");
        driver.manage().window().maximize();

        screenshot.take (this, driver, "LoginR C02");

        driver.switchTo ().defaultContent ();
        driver.switchTo ().frame ("frmbody").switchTo ().frame ("menu"); //main - suboption0001

        driver.findElement(By.cssSelector("b")).click();
        screenshot.take (this, driver, "LoginR C03");

        driver.findElement(By.linkText("Log Off")).click();
        screenshot.take (this, driver, "LoginR C04");

        //REPORTE NO BORRAR.
        Report.getInstance ().createReport (this, screenshot.getImages (),usuario);

        driver.quit();
    }

}

By other hand, these are my POM dependencies:

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>${junit.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-chrome-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-remote-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-firefox-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-server</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-ie-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-edge-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-opera-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-safari-driver</artifactId>
        <version>${selenium.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi</artifactId>
        <version>${apache.poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
        <version>${apache.poi.version}</version>
    </dependency>
    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>${testng.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>io.appium</groupId>
        <artifactId>java-client</artifactId>
        <version>${appium.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>${cucumber.version}</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>${cucumber.version}</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>gherkin</artifactId>
        <version>${gherkin.version}</version>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-java</artifactId>
        <version>1.0.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-junit</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-core</artifactId>
        <version>1.2.5</version>
        <scope>test</scope>
    </dependency>

I have look for help, but I'm new in Cucumber. Could you please help me with this?


Answer:

The problem is that you're not using the Cucumber runner anymore. The Parameterized runner runs your test with a standard BlockJunit4ClassRunner for each set of parameters. Therefore it discovers test by looking for method with the @Test annotation which you don't have anymore.

What you want to do is using the Parameterized runner but let it internally use the Cucumber runner. Since JUnit 4.12 this is possible:

@RunWith(Parameterized.class)
@UseParametersRunnerFactory(CucumberRunnerFactory.class)
public class CucumberStepDefs extends CoopeuchAutomatedWebTest {

    public static class CucumberRunnerFactor
            implements ParameterizedRunnerFactory {

        public Runner createRunnerForTestWithParameters(
            TestWithParameters test
        ) throws InitializationError {
            try {
                return Cucumber(test.getTestClass().getJavaClass());
            } catch (IOException e) {
                throw new InitializationError(e);
            }
        }
    }

    @Parameterized.Parameters
    public static Object[] data() {
        return SetDatos.getInstance().getData(CucumberStepDefs.class);
    }

    @Parameterized.Parameter(value = 0)
    public String usuario;

    ...
}

Question:

I've run into a wall when attempting to write my first step defs for a Scenario Outline in Cucumber.

I am using Gherkin features in Cucumber where my step defs are calling my various page classes which will drive and check the page using Selenium. This framework is in Java.

I have got through my scenarios OK so far but I now have a feature which looks a bit like the following:

Given I have started a policy amendment request application
When I <Colour> selected a Colour
And I <Number> select a Number
Then I <Date> be expected to populate a date the change is effective from

      Examples:
        |Colour    | Number | Date      |
        |Have      | Donot  | Will      |
        |Havenot   | Do     | Willnot   |

The question I have here is around how this is handled at step Def. If I look at the step When I <Colour> selected a Colour then I know that I can add a step def as follows to pick up this line

@When("^I \"([^\"]*)\" selected a Colour$")
public void iColourSelectedA(String colour) throws Throwable 

But this will pass in a string of "Have" and "Have not". I am wanting each input from this step to drive drive my application differently. So I'm wondering how best to do handle this.

The code I want to drive execute is:

objPolicyAmendRequest.setColour();

So in one instance (when passed in string = "Have") I want to pass in a value into my method such as objPolicyAmendRequest.setColour("Blue");

and the other (when passed in string = "Have not") I dont want to pass anything to this method.

I'm guessing I need to go down the line of an if statement but unsure if there is way Cucumber helps with this or not.

Hope I'm making sense. I'm still a bit new to programming!


Answer:

on your step for

@When("^I \"([^\"]*)\" selected a Colour$")
public void iColourSelectedA(String colour) throws Throwable 

you can add a condition for the value color.

if(colour.equalsIgnoreCase("Have"){
  //Some Logic Here
} else {
  //Some Logic Here
}

you can also use switch if you are expecting different values for Colour

Question:

 I have used cucumber BDD for my testcases with testng as the test engine. I have added the necessary jars in my POM.xml as mentioned below. I am using selenium 2.53 and using Firefox browser.

<!-- language: lang-xml -->

    <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.11</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/info.cukes/cucumber-testng -->
    <dependency>
        <groupId>info.cukes</groupId>
        <artifactId>cucumber-testng</artifactId>
        <version>1.2.5</version>
    </dependency>        

In runner class I have inherited the `AbstractTestNGCucumberTests` as below :      

        package com.cucumber.bhsibase.runner;        
        import org.junit.runner.RunWith;        
        import cucumber.api.CucumberOptions;
        import cucumber.api.junit.Cucumber;
        import cucumber.api.testng.AbstractTestNGCucumberTests;        
        @RunWith(Cucumber.class)
        @CucumberOptions(features = "src/test/resources", glue = "com.cucumber.bhsibase.party.tests")
        public class TestRunner extends AbstractTestNGCucumberTests {       
        }

I want to launch the browser with the url, so I have added that part of the code in a method with `@BeforeTest` annotation, but nothing happens. Tried the same using `@BeforeCLass` too, but it's the same.

Please find the code below: 

        public class PartyBase {

            // public static WebDriver driver;

            ReadXML readxmlobj = new ReadXML();

            final static Logger logger = Logger.getLogger(PartyBase.class);


            ConfigReader reader = new ConfigReader();
            public static WebDriver driver;

        @BeforeTest
            public void geturl() throws Exception {
                logger.info("Entering the execute message");

                driver = new FirefoxDriver();
                logger.info("Mozzilla Browser opens");
                driver.get(reader.readurls("ExpressURL"));
                logger.info("Navigate to express");
                driver.manage().window().maximize();
                driver.manage().timeouts().implicitlyWait(60, TimeUnit.SECONDS);
            }

Please let me know how to proceed ahead with this. The code runs fine only if the method is called explicitly in the given step definition of each scenarios.    
 This issue is same if I use `@before` annotation of Junit as well.  

My Testng.xml :

<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="Party" parallel="none">
<test name = "Base Party Validation">
<classes>
<class name ="com.cucumber.bhsibase.runner.TestRunner"></class>
</classes>
</test>
</suite>

I have added just my testrunner class . I was under the impression that irrespective of the class added in the testng.xml , the beforetest annotation will be run before other methods . Unable to proceed ahead . Do I need to add any other classes inside the testng.xml .


Answer:

Your suite xml contains reference to only the TestRunner class, but it looks like your annotated configuration methods reside in a different class (PartyBase in your case) which isn't being included in the suite xml file.

So you have two options:

  1. You can include PartyBase also in your suite xml file (or)
  2. move those annotations into your TestRunner class itself.

Question:

In the project Structure defined like below,

  • src/main/java -- Config (RunCukesTest.java) -- StepDefinitions
  • src/test/resources -- features/login

When I run from RunCukesTest.java using RunAs --> JUnit Test, Step Definitions cannot be found by runner

When I click find Step, opens the right file. Couldn't understand where the issue is because the code was running few days back. File is downloaded from here

https://drive.google.com/open?id=0B4SgyzyvwKhiVTRmRDZuNXNTSjA

Runner class code

package helpers;

import org.junit.runner.RunWith;

import cucumber.api.CucumberOptions;
import cucumber.api.junit.Cucumber;
//features= "src/test/resources/features/navigation",

@RunWith(Cucumber.class)
@CucumberOptions(
        features = {"classpath:features"},
        plugin = {"pretty", "html:target/cucumber-html-report"},
        tags = {"@OnlyOneTime"},
//      dryRun = true,
        monochrome = true
        )
public class RunCukesTest{

}

Answer:

Running it as a Cucumber feature, it works well, but if I provide glue={"stepDefinitions"} and try running it from runner then NullPointerException is thrown,

This problem is arising from hooks not being found. But If I move @Before and @After to the SDLogin classs, then It works well.

Question:

I created a automated test scenario using selenium + cucumber on java, and when I try to execute my test nothing occur. I don't know what I did worng but I think that something happend with my feature, because exist warning on the following messages "No definition found for I try to login on facebook", "No definition found for I put my user "email"", "No definition found for I put my password "pass"" and "No definition found for validate login".

I imported these jars using maven: cucumber-java : 1.2.5/cucumber-junit : 1.2.5/selenium-java : 3.0.1/selenium-firefox-driver : 3.0.1/junit : 4.12

RunTest.java

package com.tdd.facebook;   

import org.junit.runner.RunWith; 

import cucumber.api.junit.Cucumber;
import cucumber.api.CucumberOptions;

@RunWith(Cucumber.class) 
@CucumberOptions(
        format = {"pretty", "html:target/cucumber"},
        features = {"src/test/resources"}
        ) 

public class RunTest {

    public RunTest() {
        // TODO Auto-generated constructor stub
    }

}

LoginSteps.java

package com.tdd.facebook;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

import cucumber.api.PendingException;
import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class LoginSteps {

    WebDriver driver = null;

    @Given("^I try to login on facebook$")
    public void i_try_to_login_on_facebook() throws Throwable {

        System.setProperty("webdriver.gecko.driver", "C:\\Caio\\Selenium\\geckodriver.exe");
        WebDriver driver = new FirefoxDriver();
        driver.get("https://www.facebook.com/");        
        throw new PendingException();
    }

    @When("^I put my user \"([^\"]*)\"$")
    public void i_put_my_user(String email) {
        driver.findElement(By.id(email)).click();
        driver.findElement(By.id(email)).sendKeys("UserTest");
    }

    @When("^I put my password \"([^\"]*)\"$")
    public void i_put_my_password(String pass){ 
        driver.findElement(By.id(pass)).click();
        driver.findElement(By.id(pass)).sendKeys("Test");
    }

    @Then("^validate login$")
    public void validate_login() throws Throwable {
        System.out.println("Login OK");
    }

    public LoginSteps() {
        // TODO Auto-generated constructor stub
    }

}

Login.feature

Feature: Login on facebook

Scenario: Check if the login is successful
Given I try to login on facebook
When I put my user "email"
When I put my password "pass"
Then validate login

pow.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>com.tdd</groupId>
    <artifactId>facebook</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>facebook</name>
    <url>http://maven.apache.org</url>

    <properties>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-java</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>info.cukes</groupId>
            <artifactId>cucumber-junit</artifactId>
            <version>1.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-java</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-firefox-driver</artifactId>
            <version>3.0.1</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
</project>

Answer:

You need to add glue option to cucumberoptions with the path to the step definition classes. Use glue="com.tdd.facebook". I am not sure about this but you might want to remove the constructor in the runner RunTest.

In the LoginStps class - i_try_to_login_on_facebook() method, you are declaring another driver variable and initializing it. Thus the driver field of the class will remain null. Remove this. Also in the same method you are throwing a k. As you have implemented the step you do not need it anymore.

Also do check if all the jars are imported in the pom. I think you are missing some jars. Check the cucumber java page.

Question:

I am automating a web page using cucumber and selenium in java, and I have this xpath

      .//*[@id='chosen_motivos_investimentos_chosen']/div[1]/ul[1]

and inside the ul[1] I have a bunch of li, in this case I have this portion of html:

<ul class="chosen-results">
<li class="active-result" style="" data-option-array-index="1">LA - Media Buying Fees ‐ Traditional</li>
<li class="active-result" style="" data-option-array-index="2">LL - Marketing Development</li>
<li class="active-result" style="" data-option-array-index="3">LQ - Media Buying Fees ‐ Digital</li>
<li class="active-result" style="" data-option-array-index="4">LU - Media Costs ‐ Traditional</li>
<li class="active-result" style="" data-option-array-index="5">LV - Advertising Production Costs ‐ Traditional</li>
</ul>

And I want to click in a specific li to select, this specific is given via parameter (String despesa), I have tried this:

    Thread.sleep(2000);
    wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//*[@id='chosen_motivos_investimentos_chosen']/a"))).click();
    List<WebElement> dropDespesa = driver.findElements(By.xpath(".//*[@id='chosen_motivos_investimentos_chosen']/div[1]/ul[1]"));
    i = dropDespesa.iterator();
    while(i.hasNext()){
        WebElement row = i.next();
        if(row.getText().equalsIgnoreCase(despesa)){
            System.out.println("Igual");
            row.click();
        }
        System.out.println(row.getText());
    }

But webdriver never goes inside if, and I already debugged and made sure that despesa is in fact equals row.getText()


Answer:

You can just locate the desired li by text and click it:

// open up the dropdown
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath(".//*[@id='cho‌​sen_motivos_investimentos_chosen']/a"))).click();

WebElement dropDespesa = driver.findElement(By.xpath(".//*[@id='chosen_motivos_investimentos_chosen']/div[1]/ul[1]"));

dropDespesa.findElement(By.xpath(".//li[. = '" + despesa + "']")).click();

Question:

I'm practicing with the Cucumber automation framework so I can use it for a project at work. I'm using Selenium WebDriver to interact with the browser. Right now I'm just testing that a Google search does in fact return correct results. My feature file is here:

Feature: Google

    Scenario: Google search
        Given I am on the Google home page
        When I search for "horse"
        Then the results should relate to "horse"

This is my Java class with the step definitions:

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.junit.Assert;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;

public class StepDefinitions {

    WebDriver driver = null;

    @Given("^I am on the Google home page$")
        public void i_am_on_the_Google_home_page() throws Throwable {
        driver = new FirefoxDriver();
        driver.get("https://www.google.com");
    }

    @When("^I search for \"([^\"]*)\"$")
    public void i_search_for(String query) throws Throwable {
        driver.findElement(By.name("q")).sendKeys(query);
        driver.findElement(By.name("btnG")).click();
    }

    @Then("^the results should relate to \"([^\"]*)\"$")
    public void the_results_should_relate_to(String result) throws Throwable {
        System.out.println(driver.getTitle());
        Assert.assertTrue(driver.getTitle().contains(result));
    }
 }

To test that it does return related results, I'm just asserting that the page title contains the search query. Right now, it's failing the last step because driver.getTitle() is returning "Google", and not the expected "horse - Google Search".

I'm not sure why it's doing this. I've checked the HTML of the results page, and the title is what I expected it to be. But Selenium is not returning the right result. Can someone explain to me why and how I can fix it?


Answer:

Answer:

Probably you need to add some wait time before asserting the page title, because some times driver actions are pretty quick, that may cause assertion failures

@Then("^the results should relate to \"([^\"]*)\"$")
    public void the_results_should_relate_to(String result) throws Throwable {
        WebDriverWait wait = new WebDriverWait(driver, 10);
        WebElement element = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("some element in page"))));
        System.out.println(driver.getTitle());
        Assert.assertTrue(driver.getTitle().contains(result));
    }

Question:

Currently, I have set up an automation test framework which performs the following:

  1. Executes specific tests concurrently (i.e. x3 tests at the same time).
  2. The framework uses Cucumber BDD.
  3. I need to store and share data across steps.

I need your advice in relation to using static methods and variables when running tests concurrently, will the data be stored correctly even when running the tests concurrently?

public class Chat_Pojo {

    private static String messageToSend;

    public static void storeUniqueMessage(String message) {
        messageToSend = message;
    }

    public static String getUniqueMessage() {
        return messageToSend;
    }

    public static void wipeMessage() {
        messageToSend = null;
    }
    ...
}


Answer:

private static String messageToSend; belongs to Chat_Pojo class only, so if you do not want to share that value, you should either modify it with private static ThreadLocal<String> messageToSend. In this case each thread will have its own messageToSend value. Respectively if you want to get that value, you need to call set() or get() If you want to share that value between threads, you need to synchronize modification methods ( public static void storeUniqueMessage(String message) and public static void wipeMessage() )

Question:

I want to run the same feature files on different browsers sequentially. For example TestingExpression.feature,TestingExpression2.feature,.... all these feature files have to run on browsers(Chrome,Mozilla and IE) sequentially


Answer:

I'd suggest writing a shell script (batch file) that does something like

cucumber BROWSER=chrome
cucumber BROWSER=mozilla
cucumber BROWSER=ie

and have something in your cucumber setup that picks up the BROWSER environment variable and configures whatever you are using to drive your browsers to use the appropriate one.

This will collate all you chrome, mozilla and ie results together. You can modify this approach to pass in extra arguments to cucumber so you can control which features/scenarios are run.

Question:

Error are as under:-

Multiple markers at this line

- Syntax error, insert ")" to complete MethodDeclaration
- Syntax error on token ".", @ expected after this token
- Syntax error, insert "Identifier (" to complete MethodHeaderName
- Syntax error on token ",", < expected
- Syntax error, insert "SimpleName" to complete QualifiedName

System.setProperty is a part of which jar file or where it is present? so that I can access it and use in my program.

public class Loginstepdef {

        System.setProperty("webdriver.chrome.driver","E:\\Selenium\\chromedriver\\chromedriver.exe");
        WebDriver driver = new ChromeDriver();


        @Given("^I am on the login page of the application$")
        public void output()throws InterruptedException
        {
            driver.get("https://motzie-staging.mobile-recruit.com/login");
            //Navigation navigator=driver navigator();
            //navigator.to(http://10.10.5.56/login);

        }

        @When("^I login with username (.*) and password(.*)$")
        public void output2(String username, String password) throws InterruptedException 
        {
            //WebElement loginfield = driver.findElement(By.className("ng-scope"));
            WebElement loginfield = driver.findElement(By.id("username"));
            loginfield.sendKeys(username);
            loginfield.sendKeys(password);
            WebElement loginbutton = driver.findElement(By.className("ng-scope"));  
            loginbutton.click();
        }

        @Then("^Login successfully in that account$")
        public void output3() throws InterruptedException
        {
            System.out.print("login successfully");
        }

}              

Answer:

The Key and the Value with in System.setProperty are from Java System Class Method and both accepts String values. Hence pressing ctrl+space won't fetch you optimum results.

The error you are seeing is coming out of the Value field :

"E:\Selenium\chromedriver\chromedriver.exe"

You have to pass the absolute path of the WebDriver variant through either of the following options:

  • Escaping the back slash (\\) e.g. "E:\\Selenium\\chromedriver\\chromedriver.exe"
  • Single forward slash (/) e.g. "E:/Selenium/chromedriver/chromedriver.exe"

Note : You can find a detailed discussion in Exception in thread "main" java.lang.IllegalStateException:The path to the driver executable must be set by the : system property


Update

When you are using cucumber you have to put the initialization part of WebDriver within a method scope as follows :

WebDriver driver;

@Given("^Open Firefox and Start Application$")
public void Open_Firefox_and_Start_Application() throws Throwable 
{
    System.setProperty("webdriver.chrome.driver", "E:\\Selenium\\chromedriver\\chromedriver.exe");
    driver =  new ChromeDriver();
}

Question:

i'm junior qa automation and have as a task write module for header and category. Our QA senior used webdriver + java + cucumber. Please show me some example how to write some module


Answer:

Just go with page object model. It's simple only. Refer this link. http://toolsqa.com/selenium-webdriver/page-object-pattern-model-page-factory/

Ex: Keep Header.java and Move the locator elements to Header.java Similarly Catergory.java and Move the locator elements to Category.java

Then SampleTest.java, Call the locator method in the test file.... That's all.......