epogrebnyak / data-rosstat-kep

Time series dataset of Rosstat Short-term Economic Indicators ("KEP") publication
http://www.gks.ru/wps/wcm/connect/rosstat_main/rosstat/ru/statistics/publications/catalog/doc_1140080765391
6 stars 6 forks source link

REFERENCE: Good review of fixtures, including modules-level. #48

Closed epogrebnyak closed 8 years ago

epogrebnyak commented 8 years ago

(Note: use as_package branch.)

I'm in root folder of this repo (rosstat-kep-data), and I call test_yaml_import.py by any of below:

set PYTHONPATH=.
py.test kep/test/test_yaml_import.py

or

python -m kep.test.test_yaml_import

test_yaml_import.py uses kep.io.docstring_to_file() to write temporarily files used in this test, essentially a fixture for the test.

  1. When doing the call above test_yaml_import.test_with_file() will write _yaml_spec_sample.txt to root folder of the repo, read it back and pass the test. Desired behaviour is to write _yaml_spec_sample.txt to kep/test/temp/_yaml_spec_sample.txt. Need a solution for this without changing test_yaml_import.py structure much.
  2. Using temporarily files to run a test seems a feature of py.test as a package. How would you implement same behaviour using a fixture. (Note: this part I know little about - additional advice/explainations welcome.)
epogrebnyak commented 8 years ago

Probably not pulled a commit for this issue yet - code in repo not updated.

gabrielelanaro commented 8 years ago

I can't find the test_yaml_import file, should I wait for the commit?

epogrebnyak commented 8 years ago

Sorry, it is here now: https://github.com/epogrebnyak/rosstat-kep-data/blob/as_packages/kep/test/test_yaml_import.py. Please check

epogrebnyak commented 8 years ago

Remaing question - part 2 from above:

Using temporarily files to run a test seems a feature of py.test as a package. How would you implement same behaviour using a fixture. (Note: this part I know > little about - additional advice/explainations welcome.)

gabrielelanaro commented 8 years ago

The idea of using temporary files for testing is a good one and I use it myself often. The purpose of using temporary files is to promote isolation --- every time you run your test you want to have a clean enviroment (it could happen in the future that some file generated by some test can interfere with other tests).

The idea can be implemented in the way you already did here but remove the generated file at the end of the test. https://github.com/epogrebnyak/rosstat-kep-data/blob/tmpdir_example/kep/test/test_yaml_import.py#L24

py.test provides this mechanism automatically, but it forces you to use pytest to run the code, I made an example here: https://github.com/epogrebnyak/rosstat-kep-data/blob/tmpdir_example/kep/test/test_yaml_import.py#L27-L40

Regarding fixtures, those are yet another way to achieve test isolation. It is possible to reuse the resource creation and destruction code for multiple tests. An example is here: https://github.com/epogrebnyak/rosstat-kep-data/blob/tmpdir_example/kep/test/test_yaml_import.py#L46-L68

Which one to use? Use which one makes you more productive. I personally like the first option (explicitly creating and destroying resources) because explicit is better than implicit, and it doesn't require pytest dependent features.

epogrebnyak commented 8 years ago

@gabrielelanaro, last remaining question - is this solution for cleanup temp files ok:

https://github.com/epogrebnyak/rosstat-kep-data/blob/master/kep/test/test_label_csv.py#L36-L37

gabrielelanaro commented 8 years ago

What you want is probably module-level fixtures. Pytest has different ways to accomplish that. https://pytest.org/latest/xunit_setup.html?highlight=teardown_module#module-level-setup-teardown https://pytest.org/latest/fixture.html#sharing-a-fixture-across-tests-in-a-module-or-class-session

One way is to use setup and teardown functions like this:

# Here you create the variable and assign it to "module", which is the current module
def setup_module(module):
    module.a = 1

# Here you can access the variable defined in setup.
def test_a_is_1():
    assert a == 1

# Here you can perform some cleanup, for example removing files
def teardown_module(module):
    pass
epogrebnyak commented 8 years ago

See also issue #69.