Skip to content

Example Tests

Below are example test cases demonstrating BDD-style usage with this framework:

Swagger API add pet test

Uses a dataprovider with 4 random pets.

Requires live Swagger API at https://petstore.swagger.io/v2/

    @pytest.mark.parametrize("pet", SwaggerPetstorePet.random(range(4)))
    def should_add(self, pet: SwaggerPetstorePet):
        (self.steps
            .given.swagger_petstore(self.rest_session)
            .when.adding(pet)
            .then.the_available_pets(yields_item(tracing(is_(pet)))))

Mocked Swagger API add pet test

Defines expected requests and then same test flow as above.

    @pytest.mark.parametrize("pet", SwaggerPetstorePet.random(range(10)))
    @responses.activate
    def should_add(self, pet: SwaggerPetstorePet):
        responses.add(
            responses.POST,
            self.configuration.resource_uri(path="pet"),
            json=EMPTY_STRING,
            status=200)
        responses.add(
            responses.GET,
            self.configuration.resource_uri(path="pet/findByStatus"),
            json=[asdict(pet)],
            status=200)
        (self.steps
            .given.swagger_petstore(self.rest_session)
            .when.adding(pet)
            .then.the_available_pets(yields_item(tracing(is_(pet)))))

TerminalX (UI) search test (Selenium/Playwright)

Requires live https://www.terminalx.com

The code is similar for Selenium and Playwright.

    # NOTE sections may be further collected in superclasses and reused across tests

    def login_section(self, user: TerminalXUser) -> Self:
        (self.steps
         .given.terminalx(self.ui_context)
         .when.logging_in_with(user.credentials)
         .then.the_user_logged_in(is_(user.name)))
        return self

    def should_login(self):
        self.login_section(self.configuration.random_user)

    def should_find(self):
        (self.login_section(self.configuration.random_user)
            .steps.when.clicking_search())

        for word in ["hello", "kitty"]:
            (self.steps
             .when.searching_for(word)
             .then.the_search_hints(yields_item(tracing(
                 contains_string_ignoring_case(word)))))

The only difference is in the test class declaration.

@pytest.mark.external
@pytest.mark.ui
class TerminalXTests(
    SeleniumTests[TerminalXSteps[TerminalXConfiguration],
                  TerminalXConfiguration]):
    _steps_type = TerminalXSteps
    _configuration = TerminalXConfiguration()
versus
@pytest.mark.external
@pytest.mark.ui
class PwTerminalXTests(
    PlaywrightTests[PwTerminalXSteps[TerminalXConfiguration],
                    TerminalXConfiguration]):
    _steps_type = PwTerminalXSteps
    _configuration = TerminalXConfiguration()

Example of overriding the default setup_method

For Selenium:

    @override
    def setup_method(self) -> None:
        from selenium.webdriver import Firefox
        from selenium.webdriver.firefox.options import Options as FirefoxOptions
        from selenium.webdriver.firefox.service import Service as FirefoxService
        from webdriver_manager.firefox import GeckoDriverManager
        if self._configuration.parser.has_option("selenium", "browser_type") \
                and self._configuration.parser["selenium"]["browser_type"] == "firefox":
            options = FirefoxOptions()
            service = FirefoxService(GeckoDriverManager().install())
            self._web_driver = Firefox(options=options, service=service)
            self._web_driver.set_window_size(1920, 1080)  # type: ignore
        else:
            super().setup_method()
In this case, it checks if browser_type is firefox. This can be set temporarily via command line, like:
pytest --config selenium:browser_type=firefox qa-pytest-examples/tests/terminalx_tests.py::TerminalXTests

For Playwright:

    @override
    def setup_method(self) -> None:
        from playwright.sync_api import sync_playwright
        if self._configuration.parser.has_option("playwright", "browser_type") \
                and self._configuration.parser["playwright"]["browser_type"] == "firefox":
            self._playwright = sync_playwright().start()
            self._browser = self._playwright.firefox.launch()
            self._page = self._browser.new_page(
                viewport={"width": 1920, "height": 1080})
        else:
            super().setup_method()

More details in Architecture TerminalX Configuration section.