Search code examples
cucumbercucumber-java

Need to pass parameter for multiple links to test in cucumber


I have written this feature file for testing multiple links in home page.I was trying to reduce number of step definitions by trying to pass parameter through feature file. I am facing problem in writing element name in feature file which can fetch every tab.There is no id mentioned so I had to take xpath(which I know is not ideal to mention in feature file" .Can u suggest any alternate way to it?

Homepage.feature

  Scenario: To Test Home Tab
      Given I am on Homepage
      When I Click on ".//*[@id='oneHeader']/div[3]/div/div[2]/nav/ul/li[1]/a/span"
      Then I am on "Home"
      And application should be closed

  Scenario: To Test Calender Tab
    Given I am on Homepage
    When I Click on "Calender"
    Then I am on "Calender"
    And application should be closed

  Scenario: To Test Lead Tab
    Given I am on Homepage
    When I Click on "Leads"
    Then I am on "Leads"
    And application should be closed

  Scenario: To Test Oppurtunities Tab
    Given I am on Homepage
    When I Click on "Oppurtunities"
    Then I am on "Oppurtunities"
    And application should be closed

  Scenario: To Test Accounts Tab
    Given I am on Homepage
    When I Click on "Accounts"
    Then I am on "Accounts"
    And application should be closed


  Scenario: To Test Contacts Tab
    Given I am on Homepage
    When I Click on "Contacts"
    Then I am on "Contacts"
    And application should be closed

  Scenario: To Test Dashboard Tab
    Given I am on Homepage
    When I Click on "Dashboards"
    Then I am on "Dashboards"
    And application should be closed

  Scenario: To Test Reports Tab
    Given I am on Homepage
    When I Click on "Reports"
    Then I am on "Reports"
    And application should be closed

Step Definition look like this

package stepDefination;

import cucumber.api.java.en.Given;
import cucumber.api.java.en.Then;
import cucumber.api.java.en.When;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;

public class SmokeTest {
    WebDriver driver;

    public SmokeTest() {
    }

    @Given("^Open firefox and start application$")
    public void Open_chrome_and_start_application() throws Throwable {
        this.driver = new FirefoxDriver();
        this.driver.manage().window().maximize();
        this.driver.get("http://test.salesforce.com/");
    }

    @When("^I enter valid \"([^\"]*)\" and valid \"([^\"]*)\"$")
    public void I_enter_valid_and_valid(String unam, String pass) throws Throwable {
        this.driver.findElement(By.xpath(".//*[@id=\'username\']")).sendKeys(new CharSequence[]{unam});
        this.driver.findElement(By.xpath(".//*[@id=\'password\']")).sendKeys(new CharSequence[]{pass});
    }

    @Then("^I should be able to login successfully$")
    public void user_should_be_able_to_login_successfully() throws Throwable {
        this.driver.findElement(By.id("Login")).click();
    }

    @Given("^I am on Homepage$")
    public void i_am_on_Homepage() throws Throwable {
        this.driver.findElement(By.xpath(".//*[@id=\'salesforceLogo\']"));
    }

    @When("^I Click on \"([^\"]*)\"$")
    public void i_Click_on(String Link) throws Throwable {
        this.driver.findElement(By.id(Link)).click();
    }

    @Then("^I am on \"([^\"]*)\"$")
    public void i_am_on(String Tab) throws Throwable {
        this.driver.findElement(By.id(Tab));
    }

    @Then("^application should be closed$")
    public void application_should_be_closed() throws Throwable {
        this.driver.quit();
    }
}

Solution

  • What you are doing here is just testing navigation from the homepage. This is a pretty low value sort of test, it takes quite a bit of work and you don't get that much out of it. That said sometimes I write these sorts of scenarios. Here is how I'd do it.

    Feature: Navigation from home page
      As a user 
      I want to be able to get to important places from the home page
      So I can use the home page as a starting point
    
    Background: 
      Given I am on the homepage
    
    Scenario: Navigate to contacts
      When I navigate to contacts
      Then I should see my contacts
    

    I would do a scenario for each piece of navigation becuase

    1. Its much clearer
    2. Reducing the number of step definitions is relatively unimportant

    I'd implement the step definitions as follows (note this is in ruby, you'll have to translate to java.

    # features/step_definitions/homepage/navigation_steps.rb
    
    When 'I navigate to contacts' do
      click_link '.nav-to-contacts'
    end
    

    Again I'll do a step definition for each thing because it is just so much simpler. Notice how i'm using css for the clicking, these means that if someone comes along and changes the text, say to 'My Contacts', we don't have to update our scenario.

    Finally I'll do the same for the `thens'

    Then 'I should see my contacts' do
      expect(page).to have_css('.contacts')
    end
    

    Some points:

    • you don't need to close the application in every scenario. Its tedious and unnecessary. Cucumber does this for you.
    • using regex's in scenarios is often counter-productive. Its much more important for a scenario to be simple and clear than it is for it to be concise. This particularly applies when the scenario fails.
    • including 'How' things are done in scenarios is a bad idea. It makes things much more expensive to change. This test will still do its jobs when some designer comes along and changes your tabs to some other UI control. How things in your scenario include: the url's and clicking
    • you have a whole file system to store your features and scenarios. Use it wisely to organise both features and step definitions. The location of a scenario/step_defintion should tell you alot about its function.

    Finally scenario outlines are one of the most overrated pieces of Cucumber, I'd strongly recommend avoiding them. They reduce code, where its least important, add complexity and are much harder to implement. When one fails it takes much longer to diagnose the problem. It really is much better to have 5 simple scenarios than one complex one.