skip to Main Content

To test our website and react native mobile app, we have created a hybrid framework using webdriver.io and cucumber.io.
We currently have separate feature files for the same functionality on both the web and mobile.

E.g
In Mobile_getMembersDetails.feature

@mobile
Scenario: As a user, I can see the list of members on the home screen
    When I am on the home screen
    Then I can see the members list on mobile home screen

In the corresponding step implementation is

@when(/^I am on the home screen$/)
public async whenIamOnHomeScreen() {
await mobileLandingPage.clickContinueButton();
await mobileHomePage.clickAllowButton();
expect(await mobileHomePage.isHeaderDisplayed()).toBe(true);
}

@then(/^I should see the members list on mobile home screen$/)
public async thenIshouldSeeMemberslistOnMobileHomeScreen() {
expect(await mobileHomePage.isMemberListIsDisplayed());
}

In Web_getMembersDetails.feature

@web
Scenario: As a user, I can see the list of members on the home page
    When I am on the home page
    Then I can see the members list on web home page

In the corresponding step implementation is

@when(/^I am on the home page$/)
public async whenIamOnHomePage() {
webHomePage.open();
expect(await webHomePage.isPageLoaded()).toBe(true);
}

@then(/^I can see the members list on web home page$/)
public async thenIshouldSeeMemberslistOnWebHomePage() {
expect(await webHomePage.isMemberListIsDisplayed()).toBe(true);
}

Even though the functionality is the same, the navigation and implementation for web and mobile are different. What is the best way to do this as a single feature file and step? We were thinking of adding @web and @mobile tags, then deciding which type of test to run based on the execution command. However, this Leeds to many if else conditions and steps will become more complex. Or having one feature file is not an good idea ? Thanks

@web @mobile
Scenario: As a user, I can see the list of members on the home page
    When I am on the home page
    Then I can see the members list on web home page

Proposed step implementation is

@when(/^I am on the home page$/)
public async whenIamOnHomePage() {
  if(driver.isMobile()){
     await mobileLandingPage.clickContinueButton();
     await mobileHomePage.clickAllowButton();
     expect(await mobileHomePage.isHeaderDisplayed()).toBe(true);
    }else {
     webHomePage.open();
     expect(await webHomePage.isPageLoaded()).toBe(true);
     }
  }

@then(/^I can see the members list on web home page$/)
public async thenIshouldSeeMemberslistOnWebHomePage() {
if(driver.isMobile()){
    expect(await mobileHomePage.isMemberListIsDisplayed());
   }else{
    expect(await webHomePage.isMemberListIsDisplayed()).toBe(true);
     }
  }

2

Answers


  1. Instead of defining a mobileHomePage and webHomePage would define a single homePage. Then when instantiating the homePage you check what kind of web driver you have.

    if(driver.isMobile())
      homePage = new MobileHomePage(driver);
    else
      homePage = new WebHomePage(driver);
    

    Now you only have to check once for each page. E.g:

    @when(/^I am on the home page$/)
    public async whenIamOnHomePage() {
      homePage.openHomePage();
      expect(await homePage.isPageDisplayed()).toBe(true);
    }
    
    @then(/^I can see the members list on web home page$/)
    public async thenIshouldSeeMemberslistOnWebHomePage() {
        expect(await homePage.isMemberListIsDisplayed()).toBe(true);
    }
    

    This does require that MobileHomePage and WebHomePage implement the same HomePage interface. So to make your whenIamOnHomePage step possible you’ll have to implement a openHomePage that either goes from the mobile landing page, to the home page, or directly opens the web home page. And something similar applies to isPageDisplayed.

    Login or Signup to reply.
  2. The interesting things with this problem is what is the overlap between web and mobile at the feature/scenario level.

    If your features and scenarios are mostly abstract enough that the behaviour you are describing is the same on native as on website, then you can think about solutions where the same step calls different implementations. Here you need to decide two things

    1. How do you tell cucumber to test native or website
    2. Where does you implementation use that information to fork between implementations

    Then you can run cucumber twice on your CI, once for native and once for website.

    If there is alot of behaviour that is specific to native or website then you can either

    1. Have separate features and implementations for each
    2. Have a single set of features and a strict convention to differentiate between native and website e.g. use @native and @website tags and insist that steps use native | website in their signature.

    Finally you can combine solutions you could end up with

    features
    native_features
    website_features
    

    With disciplined refactoring the combined solution could work very nicely. Consider the scenario

    1. You develop some new native behaviour in native_features
    2. You then consider if there is equivalent website behaviour
    3. You refactor to merge native and website into common behaviour
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search