|
1 | | -# Tests |
| 1 | +# Testing with PyTest |
2 | 2 |
|
3 | | -The most essencial step is the test |
| 3 | +To test an python app is necessary to use some test toll like nose or Pytest. Ins this example we use PyTest for simplicity. |
4 | 4 |
|
5 | | - FROM python:3.8-slim as requirements |
6 | | - COPY requirements.txt /tmp/requirements.txt |
7 | | - RUN pip install -r /tmp/requirements.txt |
| 5 | +## Writting the tests |
8 | 6 |
|
| 7 | +Pytest searches for tests based on the naming convention in the test files: |
9 | 8 |
|
10 | | - FROM requirements as unittests |
11 | | - COPY src /app |
12 | | - RUN mkdir /reports |
13 | | - WORKDIR /app |
14 | | - RUN pytest test-pass.py --junit-xml=/reports/unit.xml |
| 9 | +1. Test cases are functions with name starting with `test_` |
| 10 | + |
| 11 | +2. Test files should start with `test_` |
| 12 | + |
| 13 | +3. Classes with tests should end with `_Tests` |
| 14 | + |
| 15 | +All test cases should consist at least of an assertion |
| 16 | + |
| 17 | +```python |
| 18 | +def test_pass(): |
| 19 | + assert True |
| 20 | +``` |
| 21 | + |
| 22 | +## Configuring PyTest |
| 23 | + |
| 24 | +If you want to use your own name convention or configure other properties you can do it by creating a `pytest.ini` in the root of the test folder. |
| 25 | + |
| 26 | +In this example I just configure the junit report to generate files in the old format to be used on CI-CD tools |
| 27 | + |
| 28 | +```ini |
| 29 | +# content of pytest.ini |
| 30 | +[pytest] |
| 31 | +junit_family=legacy |
| 32 | +``` |
| 33 | + |
| 34 | +## Test Requirements |
| 35 | + |
| 36 | +Its a good practicie use a exclusive requiremts file for the testing because these tools should not be package together with the application. |
| 37 | + |
| 38 | +So we create a second file called requirements-test.txt in the sample aplication folder. |
| 39 | + |
| 40 | +```python |
| 41 | +# Pytest dependency tree for pytest==5.4.1 |
| 42 | +attrs==19.3.0 |
| 43 | +importlib-metadata==1.5.0 |
| 44 | +more-itertools==8.2.0 |
| 45 | +packaging==20.3 |
| 46 | +pluggy==0.13.1 |
| 47 | +py==1.8.1 |
| 48 | +pyparsing==2.4.6 |
| 49 | +six==1.14.0 |
| 50 | +wcwidth==0.1.8 |
| 51 | +zipp==3.1.0 |
| 52 | + |
| 53 | + pytest==5.4.1 |
| 54 | +``` |
| 55 | + |
| 56 | +The contents of this file are dependencies from the package `pytest` listed with the dependencies ccomming first and the dependants last. |
| 57 | + |
| 58 | +## Dockerfile layer |
| 59 | + |
| 60 | +On the Dockerfile we create a new layer reusing the requirement layer and naming it as test. Then we copy the app code and execute the tests: |
| 61 | + |
| 62 | +```Dockerfile |
| 63 | +FROM python:3.8-slim as requirements |
| 64 | +COPY requirements.txt /tmp/requirements.txt |
| 65 | +RUN pip install -r /tmp/requirements.txt |
| 66 | + |
| 67 | + |
| 68 | +FROM requirements as test |
| 69 | +COPY src /app |
| 70 | +RUN mkdir /reports |
| 71 | +WORKDIR /app |
| 72 | +RUN pytest --junit-xml=/reports/unit.xml |
| 73 | +``` |
| 74 | + |
| 75 | +The command who execute the tests is |
| 76 | + |
| 77 | +```Dockerfile |
| 78 | +RUN pytest --junit-xml=/reports/unit.xml |
| 79 | +``` |
| 80 | + |
| 81 | +It calls the pytest packaging passing the option `--junit-xml` that generate a report in the given path. |
| 82 | + |
| 83 | +The pytest command searches for python tests and find a simple test we added before. |
0 commit comments