Search code examples
pythonpytestbdd

How to handle environment prerequisites in BDD?


I am working on an automation test project (using Pytest BDD) and I constantly hit the problem of how to handle environment prerequisites using BDD and Gherkin. For example, almost all of the scenarios require new entities created (users/admins/sites/organizations/etc) only in order to have something to work with.

I think I shouldn't write all the prerequisite actions in the 'Given' section (it seems anti-BDD), but I don't want to get lost about what scenario sets up what and how.

For example, I would never want to create this:

Scenario: A user can buy a ticket from a webshop.
Given an item available in the webshop
And a user is created
And the user has at least one payment option set up
And the user is logged in
When the user buys the item in the webshop
Then the user owns the item

How people generally write down these actions and entities in a way that is readable and maintainable in the future?


Solution

  • One Way - Using @BeforeClass (One time setup)

    @RunWith(Cucumber.class)
    @CucumberOptions(features = "classpath:features/checkoutmodule/registereduser/",
                         glue = {"com.ann.automation.test.steps" },
                         tags = { "@SignIn" },
                       plugin = { "pretty","json:target/cucumber.json",
                                  "junit:target/cucumber-reports/Cucumber.xml", "html:target/cucumber-reports",
                                  "com.cucumber.listener.ExtentCucumberFormatter"},
                       strict = false,
                       dryRun = false,
                   monochrome = true)
    
    public class RunCuke {
    
        // ----------------------------- Extent Report Configuration -----------------------------
        @BeforeClass
        public static void setup() {
            // below is dummy code just to showcase
            File newFile = new File(Constants.EXTENT_REPORT_PATH);
            ExtentCucumberFormatter.initiateExtentCucumberFormatter(newFile,true);
            ExtentCucumberFormatter.loadConfig(new File(Constants.EXTENT_CONFIG_FILE_PATH));
            ExtentCucumberFormatter.addSystemInfo("Browser Name", Constants.BROWSER);
            ExtentCucumberFormatter.addSystemInfo("Browser version", Constants.BROWSER_VERSION);
            ExtentCucumberFormatter.addSystemInfo("Selenium version", Constants.SELENIUM_VERSION);
        }
    }
    

    Other Way - Using Background (Setup before every scenario)

    Cucumber provides a mechanism for this, by providing a Background keyword where you can specify

    • a step or series of steps which are common to all the tests in the feature file.
    • a step or series of steps should run before each scenario in the feature. Typically these will be Given steps, but you can use any steps that you need to.

    Example : Here, before every scenario/outline execution, we want user to take to home page of the site and search for a product. So let's see the implementation.

      Background: 
        Given User is on Brand Home Page "https://www.anntaylor.com/"
        Given User searches for a styleId for <Site> and makes product selection on the basis of given color and size
          | Style_ID  | Product_Size | Product_Color |
          | TestData1 | TestData1    | TestData1     |
          | TestData2 | TestData2    | TestData2     |
    
      @guest_search
      Scenario Outline: Validation of UseCase Guest User Order Placement flow from Search
        Then Clicking on Cart icon shall take user to Shopping Bag
        When Proceeding to checkout as "GuestUser" with emailId <EmailID> shall take user to Shipping Page
        And Entering FN as <FName> LN as <LName> Add as <AddL1> ZCode as <ZipCode> PNo as <PhoneNo> shall take user to payment page
        And Submitting CCardNo as <CCNo>" Month as <CCMonth> Year as <CCYear> and CVV as <CVV> shall take user to Order Review Page
        Then Verify Order gets placed successfully
    
        Examples: Checkout User Information
          | EmailID   | FName     | LName     | AddL1     | ZipCode   | PhoneNo   | CCNo      | CCMonth   | CCYear    | CVV       |
          | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 | TestData2 |
    

    Last Way - Using @Before (Setup before every scenario)

    @Before
        public void setUpScenario(Scenario scenario){
            log.info("***** FEATURE FILE :-- " + Utility.featureFileName(scenario.getId().split(";")[0].replace("-"," ")) + " --: *****");
            log.info("---------- Scenario Name :-- " + scenario.getName() + "----------");
            log.info("---------- Scenario Execution Started at " + Utility.getCurrentTime() + "----------");
            BasePage.message=scenario;
            ExtentTestManager.startTest("Scenario No . " + (x = x + 1) + " : " + scenario.getName());
            ExtentTestManager.getTest().log(Status.INFO, "Scenario No . "+ x + " Started : - " + scenario.getName());
        //  Utility.setupAUTTestRecorder();
            // --------- Opening Browser() before every test case execution for the URL given in Feature File. ---------
            BaseSteps.getInstance().getBrowserInstantiation();
        }