Skip to content

Commit e377616

Browse files
Merge pull request #170 from RSE-Sheffield/test/backend
Write unit test suite
2 parents bc80b62 + bdaee10 commit e377616

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1129
-404
lines changed

.coveragerc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Coverage report configuration
2+
# https://coverage.readthedocs.io/en/7.7.1/config.html
3+
4+
[run]
5+
source = .
6+
omit =
7+
__init__.py
8+
*/migrations/*
9+
SORT/*
10+
*/admin.py
11+
*/tests/*
12+
13+
[report]
14+
format = markdown
15+
skip_empty = true
16+
sort = Cover

.github/workflows/check-gunicorn-config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ jobs:
1414
- name: Setup Python
1515
uses: actions/[email protected]
1616
with:
17+
# This should match the version used in production
1718
python-version: "3.12"
1819
cache: "pip"
1920
- name: Install dependencies
File renamed without changes.

.github/workflows/django-check.yaml

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ on:
55
pull_request:
66
branches: [ "main", "dev" ]
77
jobs:
8-
lint:
8+
django-test:
9+
name: Run Django automated checks and tests
910
runs-on: ubuntu-24.04
1011
steps:
1112
- name: Checkout
@@ -15,12 +16,19 @@ jobs:
1516
with:
1617
# This should match the version used in production
1718
python-version: "3.12"
19+
cache: "pip"
1820
- name: Install dependencies
21+
run: pip install --requirement requirements.txt --requirement requirements-dev.txt
22+
- name: Setup Node.js
23+
uses: actions/setup-node@v4
24+
with:
25+
# This should match the version used in production
26+
node-version: 'v20.x'
27+
cache: 'npm'
28+
- name: Install JavaScript package
1929
run: |
20-
# Update pip
21-
python -m pip install --upgrade pip
22-
# https://pip.pypa.io/en/stable/cli/pip_install/
23-
pip install --requirement requirements.txt
30+
npm ci
31+
npm run build
2432
# https://docs.djangoproject.com/en/5.1/ref/django-admin/#check
2533
- name: Run Django system checks
2634
run: |
@@ -30,4 +38,13 @@ jobs:
3038
- name: Run Django test suites
3139
run: |
3240
export DJANGO_SECRET_KEY="$(python -c "import secrets; print(secrets.token_urlsafe())")"
33-
python manage.py test
41+
# Iterate over Django apps with test directories
42+
for test_dir in **/tests
43+
do
44+
echo "Testing $test_dir"
45+
# https://docs.djangoproject.com/en/5.1/topics/testing/advanced/#integration-with-coverage-py
46+
coverage run --source="home,survey" manage.py test "$test_dir" --verbosity=2 --parallel=auto
47+
done
48+
# Generate coverage report
49+
echo "## Coverage report" >> $GITHUB_STEP_SUMMARY
50+
coverage report --format="markdown" >> $GITHUB_STEP_SUMMARY

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,12 @@ pip-log.txt
3838
pip-delete-this-directory.txt
3939

4040
# Unit test / coverage reports
41+
.coverage
4142

4243
# Django stuff:
4344
*.log
4445
local_settings.py
45-
db.sqlite3
46+
*.sqlite3
4647

4748
# Sphinx documentation
4849

CONTRIBUTING.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,16 @@ Please use the [Kanban board](https://github.com/orgs/RSE-Sheffield/projects/19)
1212

1313
## Proposing changes
1414

15-
1. [Raise an issue](https://github.com/RSE-Sheffield/SORT/issues/new?template=Blank+issue) clearly describing the problem or user requirements;
16-
2. [Create a branch](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-a-branch-for-an-issue) that is associated with that issue. It can be helpful to prefix the branch name to match the type of changes e.g. `feat/123-my-feature` for features or `docs/my-guide` for documentation, etc. See [Semantic branch names](https://damiandabrowski.medium.com/semantic-branch-names-and-commit-messages-3ac38a6fcbb6).
15+
1. [Raise an issue](https://github.com/RSE-Sheffield/SORT/issues/new?template=Blank+issue) clearly describing the
16+
problem or user requirements;
17+
2. [Create a branch](https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/creating-a-branch-for-an-issue)
18+
that is associated with that issue. It can be helpful to prefix the branch name to match the type of changes
19+
e.g. `feat/123-my-feature` for features or `docs/my-guide` for documentation, etc.
20+
See [Semantic branch names](https://damiandabrowski.medium.com/semantic-branch-names-and-commit-messages-3ac38a6fcbb6).
1721
3. In that branch, make changes that aim to resolve that issue;
18-
4. Create a [draft pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests) (PR) while the changes are being designed;
22+
4. Create
23+
a [draft pull request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests) (
24+
PR) while the changes are being designed;
1925
5. When ready, mark the PR "Ready for review" and request for reviewers to look at the proposed changes;
2026

2127
## Environments
@@ -25,6 +31,15 @@ There are two main environments:
2531
- Development (the `dev` branch and the `sort-web-dev` virtual machine)
2632
- Production (the `main` branch and the `sort-web-app` virtual machine)
2733

34+
### Local development environment
35+
36+
```bash
37+
python -m venv .venv
38+
source .venv/bin/activate
39+
pip install --editable .
40+
pip install -r requirements-dev.txt
41+
```
42+
2843
## Change process
2944

3045
Any proposed changes should be proposed in pull requests that would be merged into the `dev` branch.
@@ -63,3 +78,7 @@ gitGraph
6378
# Code of Conduct
6479

6580
We expect all contributors to follow the SORT [Code of Conduct](CODE_OF_CONDUCT.md).
81+
82+
# Testing
83+
84+
Please read the [testing documentation](docs/testing.md).

README.md

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,36 @@ Please read [`docs/deployment.md`](docs/deployment.md).
9898

9999

100100
# Vite integration
101-
The SORT app uses some javascript components such as the survey configurator and the survey response form. This is
102-
implemented using the svelte framework and vite is used as the bundler. Vite also provides a live server for
103-
development which includes HMR (hot module reloading).
101+
The SORT app uses some JavaScript components such as the survey configurator and the survey response form. This is
102+
implemented using the svelte framework and vite is used as the bundler. [Vite](https://vite.dev/) also provides a live server for development which includes HMR (hot module reloading).
104103

105-
In order to integrate this into the html template, a tag library is created at `/home/templatetags/vite_integration.py`.
106-
- The `vite_client` template tag is used to include Vite's HMR javascript code.
107-
- The `vite_asset` tag is used to include asset files (e.g. typescript files) in the template.
108-
- In debug mode, this creates a link directly to the vite dev server normally located at `http://localhost:5173`
109-
- In production mode, it links to assets within the `/static/` url path.
104+
In order to integrate this into the HTML template, a [custom template tag](https://docs.djangoproject.com/en/5.1/howto/custom-template-tags/) library is created at `/home/templatetags/vite_integration.py`.
105+
- The `vite_client` template tag is used to include Vite's HMR JavaScript code.
106+
- The `vite_asset` tag is used to include asset files (e.g. TypeScript files) in the template.
107+
- In debug mode, this creates a link directly to the Vite dev server normally located at `http://localhost:5173`
108+
- In production mode, the link changes to the location of the file in the `/static/` folder
110109

110+
For more information, please [read the README](ui-components/README.md).
111+
112+
## Installation
113+
114+
Install the JavaScript package using [`npm install`](https://docs.npmjs.com/cli/v8/commands/npm-install/)
115+
116+
```bash
117+
npm install
118+
```
119+
120+
## Usage
121+
122+
The development mode will run the test page at http://localhost:5173
123+
124+
```bash
125+
npm run dev
126+
```
111127

112128
## Before deployment
113129

114-
The script files within `/ui_components` must be built into the static folder before deployment. This
130+
The script files within `./ui_components/` must be built into the static folder before deployment. This
115131
can be done by running:
116132

117133
```bash

SORT/settings.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def cast_to_boolean(obj: Any) -> bool:
3333

3434

3535
# Load environment variables from .env file
36-
load_dotenv(os.getenv("DJANGO_ENV_PATH"))
36+
load_dotenv(dotenv_path=os.getenv("DJANGO_ENV_PATH", ".env"))
3737

3838
# Build paths inside the project like this: BASE_DIR / 'subdir'.
3939
BASE_DIR = Path(__file__).resolve().parent.parent
@@ -53,25 +53,28 @@ def cast_to_boolean(obj: Any) -> bool:
5353
ALLOWED_HOSTS = os.getenv("DJANGO_ALLOWED_HOSTS", "sort-web-app.shef.ac.uk").split()
5454

5555
# Application definition
56-
5756
INSTALLED_APPS = [
5857
"django.contrib.admin",
5958
"django.contrib.auth",
6059
"django.contrib.contenttypes",
6160
"django.contrib.sessions",
6261
"django.contrib.messages",
6362
"django.contrib.staticfiles",
63+
# Plugins
6464
"django_bootstrap5",
6565
"django_extensions",
66-
"debug_toolbar",
6766
"qr_code",
6867
"crispy_forms",
6968
"crispy_bootstrap5",
70-
# apps created by FA:
69+
# SORT apps
7170
"home",
7271
"survey",
7372
]
7473

74+
if DEBUG:
75+
# https://django-debug-toolbar.readthedocs.io/en/latest/installation.html
76+
INSTALLED_APPS.append("debug_toolbar")
77+
7578
MIDDLEWARE = [
7679
# Implement security in the web server, not in Django.
7780
# https://docs.djangoproject.com/en/5.1/ref/middleware/#module-django.middleware.security
@@ -82,8 +85,9 @@ def cast_to_boolean(obj: Any) -> bool:
8285
"django.contrib.auth.middleware.AuthenticationMiddleware",
8386
"django.contrib.messages.middleware.MessageMiddleware",
8487
"django.middleware.clickjacking.XFrameOptionsMiddleware",
85-
"debug_toolbar.middleware.DebugToolbarMiddleware",
8688
]
89+
if DEBUG:
90+
MIDDLEWARE.append("debug_toolbar.middleware.DebugToolbarMiddleware")
8791

8892
ROOT_URLCONF = "SORT.urls"
8993

@@ -207,10 +211,6 @@ def cast_to_boolean(obj: Any) -> bool:
207211
)
208212
VITE_MANIFEST_FILE_PATH = os.path.join(VITE_STATIC_DIR, "manifest.json")
209213

210-
# FA: for production:
211-
212-
# EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"
213-
214214
X_FRAME_OPTIONS = "SAMEORIGIN"
215215

216216
# File uploading

SORT/test/__init__.py

Whitespace-only changes.

SORT/test/model_factory/README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Model factories
2+
3+
Create dummy objects and fixtures for testing using [Factory Boy](https://factoryboy.readthedocs.io/en/stable/) which [supports the Django ORM](https://factoryboy.readthedocs.io/en/stable/orms.html#module-factory.django).
4+

0 commit comments

Comments
 (0)