Testing ======= We try to keep our quality standards high. So, we use different tools to make this possible. We use `mypy `_ for optional static typing. We run tests with `pytest `_ framework. pytest ------ ``pytest`` is the main tool for test discovery, collection, and execution. It is configured inside ``setup.cfg`` file. We use a lot of ``pytest`` plugins that enhance our development experience. List of these plugins is available inside ``pyproject.toml`` file. Running: .. code:: bash pytest We also have some options that are set on each run via ``--addopts`` inside the ``setup.cfg`` file. Plugins ~~~~~~~ We use different ``pytest`` plugins to make our testing process better. Here's the full list of things we use: - `pytest-django`_ - plugin that introduce a lot of ``django`` specific helpers, fixtures, and configuration - `django-test-migrations`_ - plugin to test Django migrations and their order - `pytest-cov`_ - plugin to measure test coverage - `pytest-randomly`_ - plugin to execute tests in random order and also set predictable random seed, so you can easily debug what went wrong for tests that rely on random behavior - `pytest-deadfixtures`_ - plugin to find unused or duplicate fixtures - `pytest-timeout`_ - plugin to raise errors for tests that take too long to finish, this way you can control test execution speed .. _pytest-django: https://github.com/pytest-dev/pytest-django .. _django-test-migrations: https://github.com/wemake-services/django-test-migrations .. _pytest-cov: https://github.com/pytest-dev/pytest-cov .. _pytest-randomly: https://github.com/pytest-dev/pytest-randomly .. _pytest-deadfixtures: https://github.com/jllorencetti/pytest-deadfixtures .. _pytest-timeout: https://pypi.org/project/pytest-timeout Tweaking tests performance ~~~~~~~~~~~~~~~~~~~~~~~~~~ There are several options you can provide or remove to make your tests faster: - You can use ``pytest-xdist`` together with ``-n auto`` to schedule several numbers of workers, sometimes when there are a lot of tests it may increase the testing speed. But on a small project with a small amount of test it just gives you an overhead, so removing it (together with ``--boxed``) will boost your testing performance - If there are a lot of tests with database access it may be wise to add `--reuse-db option `_, so ``django`` won't recreate database on each test - If there are a lot of migrations to perform you may also add `--nomigrations option `_, so ``django`` won't run all the migrations and instead will inspect and create models directly - Removing ``coverage``. Sometimes that an option. When running tests in TDD style why would you need such a feature? So, coverage will be calculated when you will ask for it. That's a huge speed up - Removing linters. Sometimes you may want to split linting and testing phases. This might be useful when you have a lot of tests, and you want to run linters before, so it won't fail your complex testing pyramid with a simple whitespace violation mypy ---- Running ``mypy`` is required before any commit: .. code:: bash mypy server tests/**/*.py This will eliminate a lot of possible ``TypeError`` and other issues in both ``server/`` and ``tests/`` directories. We use ``tests/**/*.py`` because ``tests/`` is not a python package, so it is not importable. However, this will not make code 100% safe from errors. So, both the testing and review process are still required. ``mypy`` is configured via ``setup.cfg``. Read the `docs `_ for more information. We also use `django-stubs `_ to type ``django`` internals. This package is optional and can be removed, if you don't want to type your ``django`` for some reason.