Sharing one method between several stories

804 views
Skip to first unread message

Tesla9

unread,
Mar 23, 2015, 5:16:58 PM3/23/15
to thucydid...@googlegroups.com
Hi. I work with Thucydides + JBehave +Java. On my current project we use such organization of testing framework: classes with pages -> classes with steps -> classes with tests (bdd annotations) -> story files. I often faced with situation when appears necessary to use a method with the same annotation from one test class in another as in several stories some steps have the same name and should do the same actions. For example, we have story1 with such step "Given the user open the page" and story2 with the same step. Now I have to declare a method with annotation "@Given the user open the page" in both test classes - for story1 and story2. Is there any possibility to declare the method only in one test class (for example, for story1) and reuse it in second class for story2 without declaration in this class?

John Smart

unread,
Mar 23, 2015, 6:04:29 PM3/23/15
to Tesla9, thucydid...@googlegroups.com
Hi,

I'm not sure I understand the question, but here are some potential answers:

Short answer: In tools like JBehave and Cucumber, step definitions must be unique. You have a bit more flexibility in Cucumber to choose where your step definitions come from, but I don't think it's a good idea from a maintenance perspective to have several steps like "Given the user opens the page" that do different things. If, on the other hand, a step always does the same thing ("Given the user is on the home page"), then you can just declare it once in any class and it will be detected for any story file.

Longer answer: If you have steps like "Given the user opens the page" in your story or feature files, I would argue they are too low level. Thats what the Serenity steps are for - the BDD steps should express the intent or reason why: Why does the user open the page? What is she trying to do? Etc. Maybe try pitching the stories at a higher level, and letting the Serenity step definitions worry about what pages need to be opened.

On 24 March 2015 at 08:16, Tesla9 <anm...@gmail.com> wrote:
Hi. I work with Thucydides + JBehave +Java. On my current project we use such organization of testing framework: classes with pages -> classes with steps -> classes with tests (bdd annotations) -> story files. I often faced with situation when appears necessary to use a method with the same annotation from one test class in another as in several stories some steps have the same name and should do the same actions. For example, we have story1 with such step "Given the user open the page" and story2 with the same step. Now I have to declare a method with annotation "@Given the user open the page" in both test classes - for story1 and story2. Is there any possibility to declare the method only in one test class (for example, for story1) and reuse it in second class for story2 without declaration in this class?

--
You received this message because you are subscribed to the Google Groups "Serenity BDD Users Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to thucydides-use...@googlegroups.com.
To post to this group, send email to thucydid...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.



--
___________________________________________________
John Smart | Wakaleo Consulting  |  +61 407 247 642
Optimizing your software development process
http://www.wakaleo.com  |  john....@wakaleo.com
___________________________________________________

The dates for the 2014 BDD workshops have been scheduled! Check out our upcoming BDD/TDD Master classes and our Advanced BDD Requirements Workshops, coming soon to Sydney and Melbourne!
___________________________________________________

Tesla9

unread,
Mar 24, 2015, 5:12:05 PM3/24/15
to thucydid...@googlegroups.com, anm...@gmail.com
Hi John,
Thank you for answer my question. I think I should give code examples to clarify what I mean in the answer. So, let's suggest we have such project structure:

@NamedUrl{name="home", url="{1}/home"}
class HomePage extends PageObject{

@FindBy(id="addToBasket")
private WebElementFacade addToBasketBatton;

@FindBy(css=".continue-nav-del")
private WebElementFacade continueToDeliveryButton;

WebElementFacade getAddToBasketBatton(){
            return addToBasketBatton;
      }

WebElementFacade getContinueToDeliveryButton() {
            return continueToDeliveryButton;
      }
}

class HomePageSteps extends ScenarioSteps{

private HomePage onHomePage() {
        return getPages().get(HomePage.class);
    }

   @Step
    public void openHomePage() {
        onHomePage().go();
    }

    @Step
    public void clickAddToBasketBatton() {
        onHomePage().getAddToBasketBatton().click();
    }

    @Step
    public void clickContinueToDeliveryButton() {
        onHomePage().getContinueToDeliveryButton().click();
    }

}

public class AddProductToBasketTest extends ThucydidesJUnitStory {

   @Steps
    public HomePageSteps homePageSteps;

   @Given("the user opens home page")
    public void theUserOpensHomePage(){
                   homePageSteps.openHomePage();
    }

   @When("the user clicks add to basket")
    public void theUserClicksAddToBasket(){
                   homePageSteps.clickAddToBasketBatton();
    } 
}

public class TheUserBuysTheProductTest extends ThucydidesJUnitStory {

   @Steps
    public HomePageSteps homePageSteps;

   @Given("the user opens home page")
     public void theUserOpensHomePage(){
                   homePageSteps.openHomePage();
    }

   @When("the user clicks add to basket")
    public void theUserClicksAddToBasket(){
                   homePageSteps.clickAddToBasketBatton();
    }

   @When("the user clicks continue to delivery")
     public void theUserClicksContinueToDelivery(){
                   homePageSteps.clickContinueToDeliveryButton();
    }

}

AddProductToBasketTest.story

Scenario 1:

Given the user opens home page

When the user clicks add to basket

TheUserBuysTheProductTest.story

Scenario 1:

Given the user opens home page

When the user clicks add to basket

And the user clicks continue to delivery

__________________________________________________________________________________________________________________________________________________

So, we have two story files that contain two steps which do the same things. The question is: Is there any way to declare methods theUserOpensHomePage() and theUserClicksAddToBasket() only in class AddProductToBasketTest and then reuse them in TheUserBuysTheProductTest class without declaration here (i.e. declare only method theUserClicksContinueToDelivery() and story TheUserBuysTheProductTest uses the absent steps from AddProductToBasketTest class)? Now if I do that such steps are marked as pending.

John Smart

unread,
Mar 24, 2015, 6:15:48 PM3/24/15
to Tesla9, thucydid...@googlegroups.com
Yes, there is no obligation to put JBehave step definitions (like theUserOpensHomePage() and theUserClicksAddToBasket()) in the ThucydidesJUnitStory test runner class - they can go in any class in or underneath the package where your test runner class lives.

Lovesh Jain

unread,
Aug 18, 2016, 11:30:13 PM8/18/16
to Serenity BDD Users Group, anm...@gmail.com
Hi John, 

I am facing the same issue. I my project structure I created defintion steps of all common steps in one class and specific to functionality in other class. But when I execute the feature which calls definition steps from specific class when serenity behaves weirdly and throws exception but the moment I bring those steps into common class it runs perfectly fine.

Code:

Sales.feature file :

Scenario: Add Attention field to Quotation/SO
And user navigates to 'Sales' project
And user wait for 'kanban board' on 'Sales' page
When user click on 'Sales Orders' on 'Sales' page
And user gives Advanced Search as 'Attention' and 'is set' on 'Sales' page


CommonDefintionSteps.java :- 

@Given("^user navigates to '(.*)' project$")
public void user_navigates_to_the_project(String key) throws Throwable {
EndUserSteps.clicks_the_Element(key, "TestBase");
}

@Then("^user click on '(.*)' on '(.*)' page$")
public void clicktheElement(String key, String page) throws Exception{
EndUserSteps.clicks_the_Element(key, page);
}


SpecificDefinitionSteps.java :- 

@And("user gives Advanced Search as '(.*)' and '(.*)' on '(.*)' page$")
public void userGivesAdvancedSearch(String field, String Operation, String page) throws Exception
{
WebActions.unconditionalWait(5);
EndUserSteps.clicks_the_Element("SearchViewClear", page);

John Ferguson SmartSmart

unread,
Aug 19, 2016, 1:51:30 AM8/19/16
to Serenity BDD Users Group, Lovesh Jain, anm...@gmail.com
Hi Jain,

Without seeing your full project structure it is difficult to guess what might be wrong, but splitting the step definitions across several classes should work fine and is recommended practice. Are you sure they are all in a package at or below that of the test runner?

___________________________________________________
John Smart | Wakaleo Consulting  |  +44 7398 832273
Making smart teams collaborate better

http://johnfergusonsmart.com  | rea...@johnfergusonsmart.com
___________________________________________________

Reply all
Reply to author
Forward
0 new messages