I am testing the User message function of a web solution using pytest + selenium. The tests will generate a test message to a test user, and then log in that user to verify that the message indeed is displaying for that user.
So the test scenario is basically:
My problem is that I want to avoid creating a new AUTH token every time every test within my test class is run - I want to create a new token once that all tests use within the same test run.
What is the smartest solution to generate one new access token when invoking all tests?
Right now I have come up with something like this, which will generate a new token every time any individual test is run:
import pytest
import helpers.api_access_token_helper as token_helper
import helpers.user_message_generator_api_helper as message_helper
import helpers.login_helper as login_helper
import helpers.popup_helper as popup_helper
class TestStuff(object):
@pytest.yield_fixture(autouse=True)
def run_around_tests(self):
yield token_helper.get_api_access_token()
def test_one(self, run_around_tests):
auth_token = run_around_tests
message_helper.create_new_message(auth_token, some_message_data)
message_helper.map_message_to_user(auth_token, user_one["user_id"])
login_helper.log_in_user(user_one["user_name"], user_one["user_password"])
assert popup_helper.user_message_is_displaying(some_message_data["title"])
def test_two(self, run_around_tests):
auth_token = run_around_tests
message_helper.create_new_message(auth_token, some_other_message_data)
message_helper.map_message_to_user(auth_token, user_two["user_id"])
login_helper.log_in_user(user_two["user_name"], user_two["user_password"])
assert popup_helper.user_message_is_displaying(some_other_message_data["title"])
I have laborated back and forth a bit with the "run-around-tests" fixture but havent been able to find a solution.
You have to adapt the fixture scope to cache its results for all tests in test run ( scope='session'
), all tests in module ( scope='module'
), all tests in class (old unittest
-style tests only, scope='class'
), or for a single test ( scope='function'
; this the default one). Examples:
@pytest.fixture(scope='session')
def token():
return token_helper.get_api_access_token()
class Tests(object):
def test_one(self, token):
...
def test_two(self, token):
...
class OtherTests(object):
def test_one(self, token):
...
The token will be calculated once when first requested and kept in cache throughout the whole test run, so all three tests Tests::test_one
, Tests::test_two
and OtherTests::test_one
will share the same token value.
If you intend to write old-style test classes instead of test functions and want the fixture to be a class method (like it is in your code), note that you can only use the class
scope, so that the fixture value is shared only between the tests in the class:
class TestStuff(object):
@pytest.fixture(scope='class')
def token(self):
return token_helper.get_api_access_token()
def test_one(self, token):
...
def test_two(self, token):
...
Stuff aside:
pytest.yield_fixture
is deprecated and replaced by pytest.fixture
; autouse=True
because you explicitly request the fixture in the test parameters. It will be called anyway.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.