# # Copyright (C) 2019 FreeIPA Contributors see COPYING for license # import glob import pytest MOD_NAME = "test_module_{}" FUNC_NAME = "test_func_{}" PYTEST_INTERNAL_ERROR = 3 MODS_NUM = 5 @pytest.fixture def ipatestdir(testdir): """ Create MODS_NUM test modules within testdir. Each module contains 1 test function. """ testdir.makeconftest( """ pytest_plugins = ["ipatests.pytest_ipa.slicing"] """ ) for i in range(MODS_NUM): testdir.makepyfile( **{MOD_NAME.format(i): """ def {func}(): pass """.format(func=FUNC_NAME.format(i)) } ) return testdir @pytest.mark.parametrize( "nslices,nslices_d,groups", [(2, 0, [[x for x in range(MODS_NUM) if x % 2 == 0], [x for x in range(MODS_NUM) if x % 2 != 0]]), (2, 1, [[0], list(range(1, MODS_NUM))]), (1, 0, [list(range(MODS_NUM))]), (1, 1, [list(range(MODS_NUM))]), (MODS_NUM, MODS_NUM, [[x] for x in range(MODS_NUM)]), ]) def test_slicing(ipatestdir, nslices, nslices_d, groups): """ Positive tests. Run `nslices` slices, including `nslices_d` dedicated slices. The `groups` is an expected result of slices grouping. For example, there are 5 test modules. If one runs them in two slices (without dedicated ones) the expected result will be [[0, 2, 4], [1, 3]]. This means, that first slice will run modules 0, 2, 4, second one - 1 and 3. Another example, there are 5 test modules. We want to run them in two slices. Also we specify module 0 as dedicated. The expected result will be [[0], [1, 2, 3, 4]], which means, that first slice will run module 0, second one - 1, 2, 3, 4. If the given slice count is one, then this plugin does nothing. """ for sl in range(nslices): args = [ "-v", "--slices={}".format(nslices), "--slice-num={}".format(sl + 1) ] for dslice in range(nslices_d): args.append( "--slice-dedicated={}.py".format(MOD_NAME.format(dslice))) result = ipatestdir.runpytest(*args) assert result.ret == 0 result.assert_outcomes(passed=len(groups[sl])) for mod_num in groups[sl]: result.stdout.fnmatch_lines(["*{mod}.py::{func} PASSED*".format( mod=MOD_NAME.format(mod_num), func=FUNC_NAME.format(mod_num))]) @pytest.mark.parametrize( "nslices,nslices_d,nslice,dmod,err_message", [(2, 3, 1, None, "Dedicated slice number({}) shouldn't be greater than" " the number of slices({})".format(3, 2)), (MODS_NUM, 0, MODS_NUM + 1, None, "Slice number({}) shouldn't be greater than the number of slices" "({})".format( MODS_NUM + 1, MODS_NUM)), (MODS_NUM + 1, 1, 1, None, "Total number of slices({}) shouldn't be greater" " than the number of Python test modules({})".format( MODS_NUM + 1, MODS_NUM)), (MODS_NUM, MODS_NUM, 1, "notexisted_module", "The number of dedicated slices({}) should be equal to the " "number of dedicated modules({})".format( [], ["notexisted_module.py"])), (MODS_NUM - 1, MODS_NUM - 1, 1, None, "The total number of slices({}) is not sufficient to" " run dedicated modules({}) as well as usual ones({})".format( MODS_NUM - 1, MODS_NUM - 1, 1)), ]) def test_slicing_negative(ipatestdir, nslices, nslices_d, nslice, dmod, err_message): """ Negative scenarios """ args = [ "-v", "--slices={}".format(nslices), "--slice-num={}".format(nslice) ] if dmod is None: for dslice in range(nslices_d): args.append( "--slice-dedicated={}.py".format(MOD_NAME.format(dslice))) else: args.append( "--slice-dedicated={}.py".format(dmod)) result = ipatestdir.runpytest(*args) assert result.ret == PYTEST_INTERNAL_ERROR result.assert_outcomes() result.stdout.fnmatch_lines(["*ValueError: {err_message}*".format( err_message=glob.escape(err_message))])