Skip to content

Commit

Permalink
Merge pull request #34778 from dimagi/dm/pytest
Browse files Browse the repository at this point in the history
Replace nose with pytest
  • Loading branch information
millerdev authored Nov 11, 2024
2 parents e418bbf + 7ebdc62 commit 90bf033
Show file tree
Hide file tree
Showing 61 changed files with 1,752 additions and 2,005 deletions.
3 changes: 1 addition & 2 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
/corehq/sql_db/ @snopoke @calellowitz
/corehq/sql_proxy_accessors/ @snopoke
/corehq/sql_proxy_standby_accessors/ @snopoke
/corehq/tests/nose.py @millerdev
/corehq/tests/noseplugins/ @millerdev
/corehq/tests/ @millerdev
/corehq/util/couch.py @esoergel
/corehq/util/couch_helpers.py @millerdev
/corehq/util/datadog/lockmeter.py @millerdev
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ jobs:
fail-fast: false
matrix:
include:
- {TEST: python, NOSE_DIVIDED_WE_RUN: '05'}
- {TEST: python, NOSE_DIVIDED_WE_RUN: '6a'}
- {TEST: python, NOSE_DIVIDED_WE_RUN: 'bf'}
- {TEST: python, DIVIDED_WE_RUN: '05'}
- {TEST: python, DIVIDED_WE_RUN: '6a'}
- {TEST: python, DIVIDED_WE_RUN: 'bf'}
- {TEST: python-sharded-and-javascript}
env:
DATADOG_API_KEY: ${{ secrets.DATADOG_API_KEY }}
Expand All @@ -46,11 +46,11 @@ jobs:
- name: Run tests
env:
TEST: ${{ matrix.TEST }}
NOSE_DIVIDED_WE_RUN: ${{ matrix.NOSE_DIVIDED_WE_RUN }}
DIVIDED_WE_RUN: ${{ matrix.DIVIDED_WE_RUN }}
JS_SETUP: yes
KAFKA_HOSTNAME: kafka
STRIPE_PRIVATE_KEY: ${{ secrets.STRIPE_PRIVATE_KEY }}
run: scripts/docker test --noinput --stop -v --divided-we-run=${{ matrix.NOSE_DIVIDED_WE_RUN }} --divide-depth=1 --with-timing --with-flaky --threshold=10 --max-test-time=29
run: scripts/docker test --exitfirst -vv --reusedb=1 --divided-we-run=${{ matrix.DIVIDED_WE_RUN }} --showlocals --max-test-time=29 -p no:cacheprovider
- name: "Codecov upload"
env:
TOKEN: ${{ secrets.CODECOV_TOKEN }}
Expand Down
49 changes: 49 additions & 0 deletions .pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
[pytest]
minversion = 8.1

addopts =
--strict-markers
-pcorehq.tests.pytest_hooks
# HQ has its own (incompatible) warnings system
-pno:warnings
markers =
es_test: marker for elasticsearch tests
sharded: tests to be run against shard databases
skip_setup_users: skip user setup in importer tests
slow: marks tests as slow (deselect with -m 'not slow')

empty_parameter_set_mark = fail_at_collect
xfail_strict = true

norecursedirs =
.*
*.egg
artifacts
docker
git-hooks
locale
node_modules
requirements
scripts
sharedfiles
staticfiles

python_files =
test_*.py
tests.py
*/tests/*.py

pythonpath =
.
corehq/ex-submodules
# 'submodules' is for langcodes
submodules
submodules/commcare-translations
submodules/couchdbkit-aggregate
submodules/django-digest-src
submodules/django-no-exceptions
submodules/python-digest
submodules/xml2json

required_plugins = pytest-django
DJANGO_SETTINGS_MODULE = testsettings
16 changes: 8 additions & 8 deletions DEV_SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -1038,8 +1038,8 @@ Or, to drop the current test DB and create a fresh one
./manage.py test corehq.apps.app_manager --reusedb=reset
```
See `corehq.tests.nose.HqdbContext` ([source](corehq/tests/nose.py)) for full
description of `REUSE_DB` and `--reusedb`.
See `corehq.tests.pytest_plugins.reusedb` ([source](corehq/tests/pytest_plugins/reusedb.py))
for full description of `REUSE_DB` and `--reusedb`.
### Accessing the test shell and database
Expand Down Expand Up @@ -1102,21 +1102,21 @@ ignore:unclosed:ResourceWarning'
Personal whitelist items may also be added in localsettings.py.
### Running tests by tag
### Running tests by marker
You can run all tests with a certain tag as follows:
You can run all tests with a certain marker as follows:
```sh
./manage.py test --attr=tag
pytest -m MARKER
```
Available tags:
Available markers:
- slow: especially slow tests
- sharded: tests that should get run on the sharded test runner
- es_test: Elasticsearch tests
See http://nose.readthedocs.io/en/latest/plugins/attrib.html for more details.
See https://docs.pytest.org/en/stable/example/markers.html for more details.
### Running on DB tests or Non-DB tests
Expand All @@ -1131,7 +1131,7 @@ See http://nose.readthedocs.io/en/latest/plugins/attrib.html for more details.
### Running only failed tests
See https://github.com/nose-devs/nose/blob/master/nose/plugins/testid.py
See https://docs.pytest.org/en/stable/how-to/cache.html
## Javascript tests
Expand Down
2 changes: 1 addition & 1 deletion corehq/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ tabs
Menu structure for CommCare HQ.
tests
Contains a few tests for high-level functionality like locks, as well as tooling to run tests with
`nose <https://nose.readthedocs.io/en/latest/>`_, an extension of ``unittest``.
`pytest <https://docs.pytest.org/en/stable/>`_.
toggles.py
Toggles allow limiting functionality based on user or domain. Also see ``ex-submodules/toggle`` and ``corehq.apps.toggle_ui``.
util
Expand Down
15 changes: 12 additions & 3 deletions corehq/apps/change_feed/tests/test_data_sources.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,17 @@ def sms_data():

@sharded
class DocumentStoreDbTests(TestCase):
pass

def test_couch_document_store(self):
# this one is not included with generate_cases below because
# get_db() should not be called during test collection
_test_document_store(
self,
CouchDocumentStore,
(get_db(), 'domain', 'doc_type'),
couch_data,
'_id',
)


def _test_document_store(self, doc_store_cls, doc_store_args, data_context, id_field):
Expand All @@ -216,15 +226,14 @@ def _test_document_store(self, doc_store_cls, doc_store_args, data_context, id_f


@generate_cases([
(CouchDocumentStore, (get_db(), 'domain', 'doc_type'), couch_data, '_id'),
(CaseDocumentStore, ('domain',), case_data, '_id'),
(FormDocumentStore, ('domain',), form_data, '_id'),
(LocationDocumentStore, ('domain',), location_data, 'location_id'),
(LedgerV2DocumentStore, ('domain',), ledger_data, '_id'),
(SyncLogDocumentStore, (), synclog_data, '_id'),
(SMSDocumentStore, (), sms_data, '_id'),
], DocumentStoreDbTests)
def test_documet_store(*args):
def test_document_store(*args):
_test_document_store(*args)


Expand Down
2 changes: 1 addition & 1 deletion corehq/apps/es/tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ def checkQuery(self, query, expected_json, is_raw_query=False, validate_query=Tr
@nottest
def es_test(test=None, requires=None, setup_class=False):
"""Decorator for Elasticsearch tests.
The decorator sets the ``es_test`` nose attribute and optionally performs
The decorator sets the ``es_test`` pytest marker and optionally performs
index setup/cleanup before and after the test(s).
:param test: A test class, method, or function -- only used via the
Expand Down
1 change: 0 additions & 1 deletion corehq/apps/es/transient_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ def populate_doc_adapter_map():
from pillowtop.tests.utils import TEST_ES_TYPE, TEST_ES_MAPPING, TEST_ES_INDEX
add_dynamic_adapter("PillowTop", TEST_ES_INDEX, TEST_ES_TYPE, TEST_ES_MAPPING)

import corehq.tests.pytest_compat # noqa: F401 - to be removed after switch to pytest
from corehq.apps.es.tests.utils import TEST_ES_INFO, TEST_ES_MAPPING
add_dynamic_adapter("UtilES", TEST_ES_INFO.alias, TEST_ES_INFO.type,
TEST_ES_MAPPING)
Expand Down
17 changes: 10 additions & 7 deletions corehq/ex-submodules/casexml/apps/phone/tests/test_restore_user.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from unittest.mock import Mock, patch

import pytest
from nose.tools import assert_equal
from unmagic import use

from corehq.apps.users.models import CommCareUser, DomainMembership, WebUser
from corehq.apps.users.tests.util import patch_user_data_db_layer
Expand All @@ -24,11 +26,12 @@ def test_get_commtrack_location_id():
assert_equal(loc_id, '1')


@patch_user_data_db_layer
def test_user_types():
for user, expected_type in [
(WebUser(), 'web'),
(CommCareUser(domain=DOMAIN), 'commcare'),
]:
@pytest.mark.parametrize("user, expected_type", [
(WebUser(), 'web'),
(CommCareUser(domain=DOMAIN), 'commcare'),
])
@use("db")
def test_user_types(user, expected_type):
with patch_user_data_db_layer():
user_type = user.to_ota_restore_user(DOMAIN).user_session_data['commcare_user_type']
yield assert_equal, user_type, expected_type
assert_equal(user_type, expected_type)
5 changes: 3 additions & 2 deletions corehq/ex-submodules/dimagi/utils/tests/test_decorators.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import sys
import inspect
from io import StringIO
from unittest.mock import patch

Expand All @@ -15,7 +15,8 @@ def test_profile_decorator():
def func(arg):
args.append(arg)

with patch.object(sys.stderr, "write", output.write):
sys_stderr = inspect.signature(profile).parameters["stream"].default
with patch.object(sys_stderr, "write", output.write):
func(1)
eq(args, [1])
eq(output.getvalue(), Regex(r"test_decorators.py:\d+\(func\)"))
Expand Down
Loading

0 comments on commit 90bf033

Please sign in to comment.