Search code examples
phpbddbehatgherkin

Can I use one of scenarios as my meta-step instead of define it in Context class?


I need to define meta-step like I have an item in my order cart. But instead of creating definition for this step in Context class I want just use existing steps in some feature file. Because I already have scenario for testing feature Adding item to order cart.

Is there any existing solution? I think it is very popular use case and must have a better solution than defining meta-step in Context class.


Solution

  • Short answer: No.

    I know it might look like a very useful feature, but it would bite you back quite quickly, causing unnecesary dependencies between steps/scenarios which leads to fragile tests.

    A solution is to treat your context files as a bridge between feature files and php code. That means context file methods are short, and delegate most of work to other objects. This way there's no duplication between the contexts, you simply call other objects:

    /**
     * @Given I open the product page
     */ 
    public function iOpenTheProductPage()
    {
        $this->productPage->open();
    }
    
    /**
     * @Given I add a :product to the cart
     */ 
    public function iAddProductToTheCart($product)
    {
        $this->productPage->addToCart($product);
    }
    
    /**
     * @Given I have an item in the cart
     */ 
    public function iHaveAnItemInTheCart()
    {
        // reuse
        $this->productPage->open();
        $this->productPage->addProduct('Behat t-shirt');
    
        // ... or put the items directly to the db!
    }
    

    Also, in practice, adding an item to a cart might look a bit different depending on what we're testing.

    If you're working on a "Adding to cart" scenario, you'll probably want to go through the process of visiting the page and adding products to the cart.

    If, however, you're working on a "Viewing the mini-cart in the header" scenario, you might take shortcuts to make your test suite a bit faster. In givens, when you say "Given I have an item in the cart", you might simply put an item directly into a database/session/whatever's there. You can afford this kind of shortcut since you've covered adding items to a cart in other scenarios.

    By the way, if you're automating tests for web applications you'll find patterns like page objects very helpful.