Package: pytest-xfiles
Each test function deserves a companion - a small or large (YAML, JSON or other) file sitting beside.Providing such data can be as simple as:"""Test Romeo y Julieta by Shakespeare.
"""deftest_romeo(function_yaml):print(function_yaml)deftest_julieta(function_yaml):print(function_yaml)deftest_play(module_yaml):print(module_yaml)deftest_author(package_yaml):print(package_yaml)Run the test:$pytest-svtests/shakespeare/test_romeoyjulieta.py=============================testsessionstarts==============================...tests/shakespeare/test_romeoyjulieta.py::test_romeo{'name':'Romeo','mindmap':['Julieta','Julieta','Julieta'],'spot':'ladder'}PASSEDtests/shakespeare/test_romeoyjulieta.py::test_julieta{'name':'Julieta','mindmap':['Romeo','Romeo','Romeo'],'spot':'balcony'}PASSEDtests/shakespeare/test_romeoyjulieta.py::test_play{'story':'Romeo y Julieta','main_characters':['Romeo','Julieta'],'location':'Verona'}PASSEDtests/shakespeare/test_romeoyjulieta.py::test_author{'name':'William','surname':'Shakespeare'}PASSED===========================4passedin0.03seconds===========================Where are the files?$lstests/shakespeare/test_romeoyjulieta.*tests/shakespeare/test_romeoyjulieta.julieta.yamltests/shakespeare/test_romeoyjulieta.pytests/shakespeare/test_romeoyjulieta.romeo.yamltests/shakespeare/test_romeoyjulieta.yamland one more (for the whole packagetests.shakespeare):$lstests/shakespeare/__init__.yamltests/shakespeare/__init__.yamlFile formats supportedThe sample above shows use of YAML formatted data. Out of the box, JSON format is also supported viafunction_json,module_jsonandpackage_jsonfixtures.More formats can be supported (see below).Thefunction, themoduleand thepackageThe filetests/shakespeare/__init__.pydefines a testpackage.The filetests/shakespeare/test_romeoyjulietais a testmoduleThedef test_romeoas in:deftest_romeo(function_yaml):print(function_yaml)defines a testfunction.Currently there is no notion of testclassas I did not need it. It may appear later on.Names of data filesData file names are derived from related object (package, module, function) and use format specific extensions (.json,.yaml, special._x_, other can be added).Package data file has name__init__.pywith extension changed to format specific one, e.g.__init__.json.Module data file has name such astest_romeoyjulieta.pywith extension changed to format specific one, e.g.test_romeoyjulieta.json.In case of test function, test function name must be added. To make files more readable, thetest_part of the function is removed. Fortest_romeofunction can be e.g.test_romeoyjulieta.romeo.json.The files are typically in the same directory as relevant python test suite code.What are the._x_files?There are special fixturesfunction_xfile,module_xfileandpackage_xfile, which only return path to a file with extension._x_(and do not attempt to load the content).The._x_files are used as base for implementing other fixtures, e.g. as for JSON:@pytest.fixture(scope="function")deffunction_json(function_xfile):path=function_xfile.with_suffix(".json")withpath.open(encoding="utf-8")asf:importjsonreturnjson.load(f)As shown, thefunction_jsonsimply takes the._x_file path, replaces the extension with it’s own.jsonand returns data loaded from such file.Adding support for other data formats (e.g. CSV)Following thefunction_jsonexample above, we may load data from any other data file, e.g. for.csv:fromcsvimportreaderimportpytest@pytest.fixture(scope="function")deffunction_csv(function_xfile):path=function_xfile.with_suffix(".csv")withpath.open(encoding="utf-8")asf:returnlist(reader(f))deftest_codes(function_csv):print(function_csv)WarningUnlike the{function,module,package}_jsonand{function,module,package}_yamlfixtures, thefunction_csv(and all the variants) fixture is not provided by this pytest plugin.Such fixture is intentionally not implemented as it shall be easy to implement it using your prefered extension, delimiter, encoding, type of returned object (data, iterator…) etc.Creating fixtures based on provided dataIt is easy to take any of data availalbe and use it to create object of your preference. E.g. assuming that thepackage_yamlreturns information about author in form of dictionary with keys “name” and “surname”, one can create fixtureclassy_authorreturning specific class instance. Put following intoconftest.py:classAuthor(object):def__init__(self,name,surname):self.name=nameself.surname=surname@propertydeffull_name(self):return"{self.name}{self.surname}".format(self=self)@pytest.fixture(scope="module")defclassy_author(package_yaml):returnAuthor(package_yaml["name"],package_yaml["surname"])and use it from testtest_classy_author.py:deftest_custom_fixture(classy_author):print(classy_author.full_name)Fixtures providedHere is summary of fixtures provided. In all cases we assume we havetests/sub/test_thing.pywith a test functiontest_funand all required data files are available.{scope}_xfilefamilyEach fixture provides path to a file with base name derived from current function, module or package and with an extension“._x_”:function_xfile:tests/sub/test_thing.test_fun._x_module_xfile:tests/sub/test_thing._x_package_xfile:tests/sub/__init__._x_{scope}_jsonfamilyFixtures provide data loaded from the JSON formatted files:function_json:tests/sub/test_thing.test_fun.jsonmodule_json:tests/sub/test_thing.jsonpackage_json:tests/sub/__init__.json{scope}_yamlfamilyFixtures provide data loaded from the YAML formatted files:function_yaml:tests/sub/test_thing.test_fun.yamlmodule_yaml:tests/sub/test_thing.yamlpackage_yaml:tests/sub/__init__.yamlNote on YAML package and YAML versionSwitched frompyyamltoruamel.yamlas it supports YAML version 1.2.If you require YAML files using version 1.1, use% YAML 1.1in your YAML file.