Pytest -> How To Use Fixture Return Value In Test Method Under A Class
Solution 1:
There's a technique outlined in the py.text unittest integration documentation that may be helpful to you ... using the built-in request
fixture. Otherwise, I'm not aware of way to access the return value of a fixture without providing the named fixture as a method param.
@pytest.yield_fixture(scope="class") # <-- note class scopedefoneTimeSetUp(request, browser): # <-- note the additional `request` paramprint("Running one time setUp")
if browser == 'firefox':
driver = webdriver.Firefox()
print("Running tests on FF")
else:
driver = webdriver.Chrome()
print("Running tests on chrome")
## add `driver` attribute to the class under test -->if request.cls isnotNone:
request.cls.driver = driver
## <--yield driver
print("Running one time tearDown")
Now you can access the driver
as a class attribute in TestClassDemo
, as you have in your example (i.e. self.driver
should work).
The caveat is that your fixture must use scope='class'
, otherwise the request
object will not possess a cls
attribute.
I hope that helps!
UPDATE
I have one more class, which object in need in the TestClassDemo and I need to pass the same driver instance to the class. Consider it as class ABC
It's difficult to know without more context, but it seems to me that you can probably get away with instantiating an ABC
object at the same time that you instantiate the driver
... in the oneTimeSetUp
fixture. For example ...
@pytest.yield_fixture(scope="class")defoneTimeSetUp(request, browser):
print("Running one time setUp")
if browser == 'firefox':
driver = webdriver.Firefox()
driver.maximize_window()
driver.implicitly_wait(3)
print("Running tests on FF")
else:
driver = webdriver.Chrome()
print("Running tests on chrome")
if request.cls isnotNone:
request.cls.driver = driver
request.cls.abc = ABC(driver) # <-- hereyield driver
print("Running one time tearDown")
But if you only need the ABC instance for a test class or two, here's how you might use a fixture inside the class definition ...
@pytest.mark.usefixtures("oneTimeSetUp", "setUp")classTestClassDemo(unittest.TestCase):
@pytest.fixture(autouse=True)defbuild_abc(self, oneTimeSetUp): # <-- note the oneTimeSetup reference here
self.abc = ABC(self.driver)
deftest_methodA(self):
self.driver.get("https://google.com")
self.abc.enterName("test")
print("Running method A")
deftest_methodB(self):
self.abc.enterName("test")
print("Running method B")
I wouldn't be particularly happy with the second example. A third option would be to have another yield_fixture, or similar, that is completely separate from oneTimeSetUp
and returns an ABC instance with the driver already wrapped.
Which way is best for you? Not sure. You'll need to decide based on what you're working with.
It's proper to note for posterity that pytest fixtures are just sugar and a bit of magic. You are not required to use them at all, if you find them difficult. pytest is happy to execute vanilla unittest TestCases.
Also please explain in the answer what is the best way to use instead of yield driver instance.
Here's what I had in mind ...
@pytest.fixture(scope="class")defoneTimeSetUp(request, browser):
print("Running one time setUp")
if browser == 'firefox':
driver = webdriver.Firefox()
driver.maximize_window()
driver.implicitly_wait(3)
print("Running tests on FF")
else:
driver = webdriver.Chrome()
print("Running tests on chrome")
if request.cls isnotNone:
request.cls.driver = driver
... notice that this doesn't return (or yield) the driver object, which means that it's no longer useful to provide this fixture as a named parameter to a function/method, which should be fine if all of your test cases are written as classes (suggested by your examples).
However, if you want to use the fixture as a named parameter, don't do this.
Post a Comment for "Pytest -> How To Use Fixture Return Value In Test Method Under A Class"