python - pytest -> How to use fixture return value in test method under a class -
i have fixture returns value this:
import pytest @pytest.yield_fixture(scope="module") def onetimesetup(browser): print("running 1 time setup") if browser == 'firefox': driver = webdriver.firefox() print("running tests on ff") else: driver = webdriver.chrome() print("running tests on chrome") yield driver print("running 1 time teardown")
this fixture gets browser value fixture reading command line option.
then have test class have more 1 test methods , want consume same returned value driver proceed tests.
import pytest @pytest.mark.usefixtures("onetimesetup") class testclassdemo(): def test_methoda(self): # use driver value here # how this? # self.driver.get("https://www.google.com") self.driver.find_element(by.id, "some id") print("running method a") def test_methodb(self): print("running method b")
using self.driver fails error message
self = <test_class_demo.testclassdemo object @ 0x102fb6c18> def test_methoda(self): > self.driver.get("https://www.google.com") e attributeerror: 'testclassdemo' object has no attribute 'driver'
i aware can pass fixture argument every method want use that, not best way because need in every method , should possible pass class , use in test methods.
what best way can make driver object available methods?
edit 1:
created fixture in conftest.py suggested
@pytest.yield_fixture(scope="class") # <-- note class scope def onetimesetup(request, browser): # <-- note additional `request` param print("running 1 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") ## add `driver` attribute class under test --> if request.cls not none: request.cls.driver = driver ## <-- yield driver print("running 1 time teardown")
i have 1 more class, object in need in testclassdemo , need pass same driver instance class. consider class abc
class abc(): def __init(self, driver): self.driver = driver def entername(self): # driver instance
then in testclassdemo
@pytest.mark.usefixtures("onetimesetup", "setup") class testclassdemo(unittest.testcase): # need create object of class abc, can use here # abc = abc(self.driver) @pytest.fixture(scope="class", autouse=true) def setup(self): self.abc = abc(self.driver) # tried this, it's not working # error message shows # attributeerror: 'testclassdemo' object has no attribute 'driver' def setup_module(self): self.abc = abc(self.driver) # not work # error message -> attributeerror: 'testclassdemo' object has no attribute 'abc' def test_methoda(self): self.driver.get("https://google.com") self.abc.entername("test") print("running method a") def test_methodb(self): self.abc.entername("test") print("running method b")
this abc object should usable in other test_ methods also.
all these classes in separate modules, mean in separate .py files.
also please explain in answer best way use instead of yield driver instance.
edit 2:
for example without yield, best way run onetimeteardown also? running teardown steps after yield
@pytest.fixture(scope="class") def onetimesetup(request, browser): print("running 1 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 not none: request.cls.driver = driver
also tried using unittest class, when use def setupclass(cls), not able use objects instantiated in test_ methods. couldn't not figure out how achieve that.
i wanted provide command line arguments browser command line , when tried unittest, had write command line argument in every class. wanted provide them in 1 place only, test suite. conftest helped me here.
i had question on stackoverflow didn't response. please take @ also? python unittest passing arguments parent test class
thanks
thanks
there's technique outlined in py.text unittest integration documentation may helpful ... using built-in request
fixture. otherwise, i'm not aware of way access return value of fixture without providing named fixture method param.
@pytest.yield_fixture(scope="class") # <-- note class scope def onetimesetup(request, browser): # <-- note additional `request` param print("running 1 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 class under test --> if request.cls not none: request.cls.driver = driver ## <-- yield driver print("running 1 time teardown")
now can access driver
class attribute in testclassdemo
, have in example (i.e. self.driver
should work).
the caveat fixture must use scope='class'
, otherwise request
object not possess cls
attribute.
i hope helps!
update
i have 1 more class, object in need in testclassdemo , need pass same driver instance class. consider class abc
it's difficult know without more context, seems me can away instantiating abc
object @ same time instantiate driver
... in onetimesetup
fixture. example ...
@pytest.yield_fixture(scope="class") def onetimesetup(request, browser): print("running 1 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 not none: request.cls.driver = driver request.cls.abc = abc(driver) # <-- here yield driver print("running 1 time teardown")
but if need abc instance test class or two, here's how might use fixture inside class definition ...
@pytest.mark.usefixtures("onetimesetup", "setup") class testclassdemo(unittest.testcase): @pytest.fixture(autouse=true) def build_abc(self, onetimesetup): # <-- note onetimesetup reference here self.abc = abc(self.driver) def test_methoda(self): self.driver.get("https://google.com") self.abc.entername("test") print("running method a") def test_methodb(self): self.abc.entername("test") print("running method b")
i wouldn't particularly happy second example. third option have yield_fixture, or similar, separate onetimesetup
, returns abc instance driver wrapped.
which way best you? not sure. you'll need decide based on you're working with.
it's proper note posterity pytest fixtures sugar , bit of magic. not required use them @ all, if find them difficult. pytest happy execute vanilla unittest testcases.
also please explain in answer best way use instead of yield driver instance.
here's had in mind ...
@pytest.fixture(scope="class") def onetimesetup(request, browser): print("running 1 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 not none: request.cls.driver = driver
... notice doesn't return (or yield) driver object, means it's no longer useful provide fixture named parameter function/method, should fine if of test cases written classes (suggested examples).
however, if want use fixture named parameter, don't this.
Comments
Post a Comment