CEH
CEH

Reputation: 5909

Is it possible to inherit setup() and tearDown() methods?

I work with automation primarily in C# / Java and have been looking into Python for its speed.

In C#, I can write a class that implements a WebDriver instance, along with [SetUp] and [TearDown] methods. Then, every class containing test cases can inherit from this class, so I do not need to write my SetUp and TearDown for every test class I write.

The other benefit of SetUp / TearDown fixture is that I can use same WebDriver instance throughout all tests. SetUp will create the WebDriver instance, and pass it into test case class, where test case can use to initialize PageObjects & perform clicks etc. When test is finished, WebDriver instance gets passed back into TearDown for cleanup. This is highly efficient and easy to use.

My issue: I do not understand the Python best-practice on how to implement this functionality.

I have read through Python unittest docs here and read up on Python multiple inheritance here with little luck. I have also read this SO discussion here, but it is 10+ years old and contains many polarizing opinions. I did use discussion as guidance to get started, but I do not want to blindly write code without understanding it.

I am hung up on the part about how to actually inherit setUp(), tearDown(), and my webdriver instance. I don't want to declare a new webdriver instance, and re-write setUp() and tearDown() methods for every single test class, as this seems inefficient.

Here's what I've tried:

This is SetUp / TearDown fixture which is meant to handle setup and teardown for ALL test cases, and also keep track of singleton WebDriver instance.

Project Directory Structure:

Project Directory Structure

base_test_fixture.py

from selenium import webdriver
import unittest


class BaseTestFixture(unittest.TestCase):

    driver = None

    def setUp(self):
        print("Running SetUp")
        self.driver = webdriver.Chrome()

    def tearDown(self):
        print("Running Teardown")
        self.driver.close()
        self.driver.quit()

Here is test_webdriver.py:

import unittest
import BaseTestFixture


class TestWebDriver(BaseTestFixture.SetUpTearDownFixture):

    def test_should_start_webdriver(self):
        super.setUp()
        print("Running test 1")
        super.driver.get("https://www.google.com")
        assert "Google" in self.driver.title
        super.tearDown()

    def test_should_navigate_to_stackoverflow(self):
        super.setUp()
        print("Running test 2")
        super.driver.get("https://www.stackoverflow.com")
        assert "Stack Overflow" in self.driver.title
        super.teardown()


if __name__ == '__main__':
    unittest.main()


Here's the error my class declaration is showing: AttributeError: module 'BaseTestFixture' has no attribute 'SetUpTearDownFixture'

Is it possible to implement a single WebDriver, setUp(), and tearDown() for all Python test cases?

Upvotes: 2

Views: 1007

Answers (1)

Breaks Software
Breaks Software

Reputation: 1761

You are very close. the Python convention is that your module should be named with underscores, so I would rename BaseTestFixture.py to base_test_fixture.py, and the class in the module would be the camelcase version of the module name.

that would give us, base_test_fixture.py:

from selenium import webdriver
from unittest import TestCase


class BaseTestFixture(TestCase):

and test_web_driver.py:

import unittest
from base_test_fixture import BaseTestFixture


class TestWebDriver(BaseTestFixture):

If you're still having trouble, the problem may be in the directory structure of your package, so share that with us by editing your question above to indicate the structure of your directory and files.

Also, within your test, since the test class inherits self.driver, you just have to refer to it as self.driver (no super.).

Also, setUp() and tearDown() are automatically called by unittest, so you don't have to call them explicitly.

Upvotes: 3

Related Questions