On Tue, Dec 15, 2020 at 6:07 PM Diptesh Choudhuri
<
diptesh....@gmail.com> wrote:
> Instead of removing the default test runner altogether, I can work on adding a TESTING_BACKEND variable in settings.py with possible values being 'django.testing.backends.pytest' (default) or 'django.testing.backends.DefaultRunner'. This way we need not compromise on the features that the default runner provides over pytest. Meanwhile I could work on some the issues pytest has by contributing to pytest-dev.
I would be against both the original proposal to switch Django to
pytest, and this proposal.
And it's not just because I'm a little bit biased here -- though I am,
in that I personally dislike pytest and when I use it in personal
projects I use it solely as a runner, where the tests themselves all
use the unittest and mock modules in the Python standard library.
There are several independent reasons why I don't think either of
these proposals is a good fit for Django:
One is that even though it's easier at first to add dependencies to
Django now than it was 15 years ago, every dependency still should be
carefully considered. It wasn't too long ago that this proposal would
have been "switch the Django test runner to nose", and now nose is
unmaintained and deprecated (its last release was in 2015) and though
there's a maintained "nose2" fork, it's not compatible with the
original and doesn't have anywhere near the development momentum the
original had. You might observe that pytest shows no signs of having
that happen to it, but the fact that it *can* happen has to be
considered when we're talking about integrating it into one of
Django's core components; we can think it's likely, and be hopeful,
that pytest would still be around and actively maintained 5 years from
now, but we can be much more certain that the Python standard
library's unittest module will still be around and actively
maintained.
Another is that pytest would be effectively a test-only dependency,
and the history of *those* in Python projects is largely an unhappy
and complicated one. It would create a potential risk for unwary users
(forgetting to install the extra dependency, or to do "pip install
Django[pytest]" or similar), or force every installation of Django --
including production installations which often don't want a large
third-party framework that won't be used at all in production -- to
also install pytest.
Still another is the basic incompatibility between pytest and unittest
runners. While it's true that Django lets you configure a lot of
things, they all are handled through carefully normalized APIs, so
that you don't notice the difference. This is what lets you start out
development with a local SQLite database and switch to Postgres when
you deploy, for example, or swap out cache or session or
authentication or email-sending backends without needing to rewrite
your own code that uses those features, because Django provides
normalized APIs for accessing whichever backend it's been configured
to use. But pytest is not that simple: pytest can run tests written in
unittest style, but unittest cannot run tests written in pytest style.
Only pytest -- which understands its own conventions for setup,
fixture loading, and so on -- can do this. Which means that if I write
my Django app using pytest style, and you want to use it in your
project that's otherwise completely unittest style, you cannot
integrate with full testing support unless you also switch your whole
project's configuration to pytest. That's a *big* difference from,
say, switching to a new auth backend.
So I'm in agreement with others in this thread that if you want to
improve things for people who prefer to use pytest, contributing to
pytest, pytest-django, and related projects would be a fine way to do
so. But trying to switch Django itself to pytest, or to introduce a
"test backend" concept that would have a pytest runner, does not seem
to me like a good idea.