skip to Main Content

The idea is I have a set of conditions like: positive, negative, even, odd.

And I have a bunch of tests, which can be run on combination of these conditions (‘positive+even’ or ‘negative+odd’)

But I want to run only one tests with any value from each condition. E.g.:

positive+even:

2

negative+odd

-3

In this example, I want to mark tests, so pytest automatically picks value depending on condition and run test only once.

I was thinking about creating a fixture for each condition and pass all fixture to tests or using pytest_generate_tests.

http://doc.pytest.org/en/latest/example/parametrize.html#deferring-the-setup-of-parametrized-resources this example is almost what I want, but instead of run the test for each DB, I’d like it to run once and with supporting of combination conditions like any(‘oracle’, ‘Db2’, ‘mysql’) + any(‘win’, ‘linux’).

Could you please advise about preferable way of doing this? should it be implemented in a complex fixture or using pytest-tags plugin + addition parsing/handling the combination in conftest.py or there are other ways

Update:

Example

@pytest.fixture(scope='function')
def connection(request):
    oracle_dbs = ['db1', 'db2', 'db3_19c']
    mysql_dbs = ['db1', 'db2', 'db3']
    connect = Create_connector(request.tag[0])
    if request.tag[1] == 'oracle':
        if and not request.tag[2]:
            connect.oracle(random.choice(oracle_dbs))
        else:
            connect.oracle(random.choice(db3_19c))
    if request.tag[1] == 'mysql':
        connect.mysql(random.choice(mysql_dbs))
    return connect

@pytest.mark.tag('any_os', 'any_db')
def test_run_any_query(connection):
    pass

@pytest.mark.tag('linux', 'oracle')
def test_run_query_lin_oracle(connection):
    pass

@pytest.mark.tag('linux', 'oracle', '19c')
def test_run_query_lin_oracle(connection):
    pass

Explanation:

1 test, it finds one suitable environment by tags and run test only once, not all combinations

2 test, it finds one suitable environment as well (so it can be ubuntu/debian/gentoo/etc and any of oracle version), but still it should be run only once.

3 test, it picks only one oracle db that satisfies the condition and run it only once as well

Can I get markers or tags in pytest_generate_tests(metafunc) function?

2

Answers


  1. Chosen as BEST ANSWER

    It has been done as the below: test_numbers.py:

    import pytest
    
    @pytest.mark.env('EVEN', 'NEGATIVE')
    def test_sum(number):
        assert (number < 0) and number % 2 == 0
    
    
    @pytest.mark.env('ODD', 'POSITIVE')
    def test_substraction(number):
        assert (number > 0) and number % 2 == 1
    

    conftest.py:

    from _pytest.python import Metafunc
    import random
    import pytest
    
    
    def pytest_generate_tests(metafunc: Metafunc):
        if 'number' in metafunc.fixturenames:
            for marker in metafunc.definition.iter_markers():
                if marker.name == 'env':
                    number = random.randint(-10, 10) * 2
                    if 'ODD' in marker.args:
                        number += 1
                    if 'POSITIVE' in marker.args:
                        if number < 0:
                            number *= -1
                    if 'NEGATIVE' in marker.args:
                        if number > 0:
                            number *= -1
                    metafunc.parametrize('number', [number], indirect=True, scope='function')
    
    
    @pytest.fixture
    def number(request):
        return request.param
    

  2. There seem to be two concerns in your question:

    Parameterize test

    As you already linked in your question, you can parameterize tests.

    e.g.

    import pytest
    
    
    @pytest.mark.parametrize("db_name,os_name", [
        ("oracle", "win"),
        ("Db2", "linux")
    ])
    def test_db_os_combinations(db_name: str, os_name: str):
        print("ndb_name={db_name}, os_name={os_name}".format(
            db_name=db_name,
            os_name=os_name
        ))
    

    Find all “combinations”

    You can simply extend the above by generating the parameter list. e.g.

    import pytest
    
    
    @pytest.mark.parametrize("db_name,os_name", [
        (db_name, os_name)
        for db_name in ['oracle', 'Db2', 'mysql']
        for os_name in ['win', 'linux']
    ])
    def test_db_os_combinations(db_name: str, os_name: str):
        print("ndb_name={db_name}, os_name={os_name}".format(
            db_name=db_name,
            os_name=os_name
        ))
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search