Reputation: 5909
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:
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
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