I need to create multiple users (by sending HTTP requests) and run login page tests with created users data (login, password)
I have fixture, that generates users and provides their login data (list of tuples like [(login1, password1), (login2, password2)] in yield. I want to use this yield data as parametrization, because I know only one correct way to run 1 test multiple times with different test data.
Here's code:
conftest.py
@pytest.fixture(scope="session", autouse=True)
def test_user_fixture():
print("INFO | Generating test user data")
user_data_set = user_data_generator()
login_data = []
for user_data in user_data_set:
login_data.append((user_data[0], user_data[1]))
if send_user_create_request(user_data) != 200: # this function sends request to create user AND returns status_code
pytest.exit("ERROR | Test user wasn't created")
yield login_data
print("INFO | Clearing test data")
test_login_page.py
@pytest.mark.usefixtures('webdriver_fixture', 'test_user_fixture')
class TestPositiveLogin:
@pytest.mark.parametrize("login, password", test_user_fixture)
def test_positive_login(self, webdriver_fixture, login, password):
driver = webdriver_fixture
page = BasePage(driver)
page.open_base_page()
page.login(login, password)
Here I tried just using fuxture as parameters, because login_data perfectly fits into parameters data format, but python says
NameError: name 'test_user_fixture' is not defined
Can you please help me solving this problem or maybe give another solution
Your current
test_user_fixturefixture returns a list of login/password. I am sure you are usingyieldbecause you want some clean up later (e.g. remove the users).My proposal is for
test_user_fixtureto return just a single login/password. Then we can parametrize this fixture using theparams=keyword:and
and
Output when
log_cli="false":Output when
log_cli="true":Notes
I assume that USERS_DATA contains
[(user, password, ...), ...]The
params=USERS_DATAparametrize the fixture. Even though this fixture is scoped at session level, it will be called once for each element inUSERS_DATA. In other word, ifUSERS_DATAcontains 2 elements, this fixture will be called twice.The
test_id()function extracts theloginfrom the test parameter, thus provide a better way to identify the tests.The
test_user_fixturereturns a tuple of(login, password), so in the test, we unpack it to make it easier:I prefer to use
loggingoverprintbecause I can turn on/off via this line inpyproject.toml:just replace
truewithfalseand I can effectively turn off all logging. I can also control the log level (e.g. WARN, INFO, DEBUG, ...) with this line:Update
If you remove the
ids=part, then the output will look like this:Notice the part inside the square brackets
test_user_fixture0andtest_user_fixture1: they are IDs whichpytestgenerate automatically and they are not helpful.What I want to place inside these square brackets are IDs which are useful such as the
loginname.According to pytest doc, the
ids=could be a sequence of IDs. That means the following works the same way:For example, if
USERS_DATAisThen,
TEST_IDSwill beAnd these IDs will be used inside of the square brackets. Note that the
ids=can also be a function which take in a single element of theparams=parameter and return an ID. In this case we have:That means
pytestwill pass each element inUSERS_DATAinto the functiontest_idand use the return value as the ID.Which method should we use? I believe the first method with
TEST_IDSare easier to understand. The second method is more powerful and that is what I use in my projects.