Skip to content

Commit

Permalink
test: add pytest and build details unit tests
Browse files Browse the repository at this point in the history
- Added pytest
- Added pytest-django (not being used for now)
- Run tests before pushing
- Updated the existing unit tests to use pytest instead of unittest
- Added utilities to perform django 'external' unit tests
- Added tests for BuildDetailsView as an example for the other django
  tests to be performed

Part of #943
  • Loading branch information
murilx committed Feb 20, 2025
1 parent f01fd09 commit 432a115
Show file tree
Hide file tree
Showing 9 changed files with 164 additions and 50 deletions.
10 changes: 7 additions & 3 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,16 @@ poetry run python3 manage.py runserver
The backend includes unit tests covering some parts of the source code. To run the tests, use the following command:

```sh
# run this for each test file in kernelCI_app/unitTests/
poetry run python kernelCI_app/unitTests/<file-name.test.py>
poetry run pytest
```

Currently you must run this command for each test file in the `kernelCI_app/unitTests/` directory.
All unit test files must follow this naming convention: `*_test.py`.

The django tests are being done 'externally', that means, instead of using the utilies the framework
has for testing (like `Client` from Django or `APIClient` from DRF) we are performing requests to the
endpoints using the built-in `requests` library from python. For that reason, for the django tests to run
it's necessary to be running the server while performing the tests. When running pytest with the server
offline, all django tests will be skipped.

# Deploy instructions

Expand Down
21 changes: 21 additions & 0 deletions backend/kernelCI_app/unitTests/ buildDetails_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from kernelCI_app.utils import string_to_json
from kernelCI_app.unitTests.utils.utils import online
from kernelCI_app.unitTests.utils.kernelCIClient import KernelCIClient
import pytest


@online
@pytest.mark.parametrize(
"build_id, status_code, has_error_body",
[
("maestro:67b62592f7707533c0ff7a95", 200, False),
("invalid_id", 200, True),
],
)
def test_get(build_id, status_code, has_error_body):
client = KernelCIClient()
response = client.get_build_details(build_id)
content = string_to_json(response.content.decode())
assert response.status_code == status_code
if has_error_body:
assert "error" in content
31 changes: 31 additions & 0 deletions backend/kernelCI_app/unitTests/filters_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from kernelCI_app.helpers.filters import should_filter_test_issue
from kernelCI_app.constants.general import UNCATEGORIZED_STRING


class TestShouldFilterTestIssue:
def test_no_issue_filters(self):
assert not should_filter_test_issue(
issue_filters=set(),
issue_id=UNCATEGORIZED_STRING,
issue_version=None,
incident_test_id="incident_test_1",
test_status="FAIL",
)

def test_unknown_filter_with_exclusively_build_issue(self):
assert should_filter_test_issue(
issue_filters={UNCATEGORIZED_STRING},
issue_id="issue1",
issue_version=1,
incident_test_id="incident_test_1",
test_status="PASS",
)

def test_unknown_issue_but_not_from_test(self):
assert not should_filter_test_issue(
issue_filters={UNCATEGORIZED_STRING},
issue_id="maestro:72697a4efbbd0eff7080781839b405bbf0902f79",
issue_version=0,
incident_test_id=None,
test_status="FAIL",
)
44 changes: 0 additions & 44 deletions backend/kernelCI_app/unitTests/treeDetails.test.py

This file was deleted.

16 changes: 16 additions & 0 deletions backend/kernelCI_app/unitTests/utils/kernelCIClient.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import requests
import urllib.parse

from django.urls import reverse


class KernelCIClient:
base = "http://localhost:8000/"

def get_endpoint(self, path) -> str:
return urllib.parse.urljoin(self.base, path)

def get_build_details(self, build_id: str) -> requests.Response:
path = reverse("buildDetails", kwargs={"build_id": build_id})
url = self.get_endpoint(path)
return requests.get(url)
15 changes: 15 additions & 0 deletions backend/kernelCI_app/unitTests/utils/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import subprocess
import pytest


def ping(host: str) -> bool:
"""
Checks if a host is online using the Linux 'ping' command.
Note: This function does not currently support Windows.
"""
param = "-c"
command = ["ping", param, "1", host]
return subprocess.call(command) == 0


online = pytest.mark.skipif(not ping("localhost"), reason="Server is not online")
68 changes: 66 additions & 2 deletions backend/poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion backend/pre-push
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/usr/bin/env sh

#TODO: pre-pushes python test
poetry run pytest
TEST_STATUS=$?
exit $TEST_STATUS
5 changes: 5 additions & 0 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ drf-spectacular = "^0.28.0"
black = "^24.4.2"
mypy = "^1.10.0"
flake8 = "^7.1.0"
pytest = "^8.3.4"
pytest-django = "^4.10.0"

[tool.pytest.ini_options]
DJANGO_SETTINGS_MODULE = "kernelCI.settings"

[build-system]
requires = ["poetry-core"]
Expand Down

0 comments on commit 432a115

Please sign in to comment.