Skip to content

Commit f573f29

Browse files
committed
test: run in parallel across 4 workers, 30s -> 13s
running test suite in parallel before we get too far we should also monitor pytest-dev/pytest-xdist#229 because right now one cannot run tests in random order as well as run in parallel until then, I've added another makefile target that can run the tests in parallel, and have left that running in CI.
1 parent df66f46 commit f573f29

File tree

4 files changed

+61
-21
lines changed

4 files changed

+61
-21
lines changed

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,14 @@ clean: ## Clean the workspace of generated resources
3131
TESTS ?= tests
3232
TESTOPTS ?= -v
3333
.PHONY: test
34-
test: ## Run the application tests
34+
test: ## Run the application tests in parallel (for rapid development)
35+
@TEST_CMD="python -m pytest -v -n 4 --cov-config .coveragerc --cov-report html --cov-report term-missing --cov=securedrop_client --cov-fail-under 100 $(TESTOPTS) $(TESTS)" ; \
36+
if command -v xvfb-run > /dev/null; then \
37+
xvfb-run $$TEST_CMD ; else \
38+
$$TEST_CMD ; fi
39+
40+
.PHONY: test-random
41+
test-random: ## Run the application tests in random order
3542
@TEST_CMD="python -m pytest -v --random-order-bucket=global --cov-config .coveragerc --cov-report html --cov-report term-missing --cov=securedrop_client --cov-fail-under 100 $(TESTOPTS) $(TESTS)" ; \
3643
if command -v xvfb-run > /dev/null; then \
3744
xvfb-run $$TEST_CMD ; else \
@@ -60,7 +67,7 @@ bandit: ## Run bandit with medium level excluding test-related folders
6067
bandit -ll --recursive . --exclude ./tests,./.venv
6168

6269
.PHONY: check
63-
check: clean bandit lint mypy test ## Run the full CI test suite
70+
check: clean bandit lint mypy test-random ## Run the full CI test suite
6471

6572
.PHONY: update-pip-requirements
6673
update-pip-requirements: ## Updates all Python requirements files via pip-compile.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ To run everything, run:
113113
make check
114114
```
115115

116+
To individually run the unit tests, run `make test` to run the suite in parallel (fast), or run `make test-random` to run the tests in random order (slower, but this is what `make check` runs and what runs in CI).
117+
116118
## Environments
117119

118120
The quickest way to get started with running the client is to use the [developer environment](#developer-environment) that [runs against a test server running in a local docker container](#running-against-a-test-server). This differs from a staging or production environment where the client receives and sends requests over Tor. Things are a lot snappier in the developer environment and can sometimes lead to a much different user experience, which is why it is important to do end-to-end testing in Qubes using the [staging environment](#staging-environment), especially if you are modifying code paths involving how we handle server requests and responses.

dev-requirements.in

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ more-itertools==4.3.0
99
mypy==0.701
1010
mypy-extensions==0.4.1
1111
pip-tools==3.1.0
12-
pluggy==0.8.0
12+
pluggy==0.13.0
1313
py==1.7.0
1414
pycodestyle==2.4.0
1515
pyflakes==2.0.0
1616
PyQt5==5.10.1
17-
pytest==3.9.3
18-
pytest-cov==2.6.0
17+
pytest==5.2.1
18+
pytest-cov==2.8.1
1919
pytest-mock==1.10.0
2020
pytest-random-order==1.0.0
21+
pytest-xdist==1.30.0
2122
sip==4.19.8
2223
typed-ast==1.3.4

dev-requirements.txt

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@
22
# This file is autogenerated by pip-compile
33
# To update, run:
44
#
5-
# pip-compile --generate-hashes --output-file=dev-requirements.txt dev-requirements.in requirements.in
5+
# pip-compile --generate-hashes --output-file dev-requirements.txt requirements.in dev-requirements.in
66
#
77
alembic==1.0.2 \
88
--hash=sha256:04bcb970ca8659c3607ddd8ffd86cc9d6a99661c9bc590955e8813c66bfa582b
9+
apipkg==1.5 \
10+
--hash=sha256:37228cda29411948b422fae072f57e31d3396d2ee1c9783775980ee9c9990af6 \
11+
--hash=sha256:58587dd4dc3daefad0487f6d9ae32b4542b185e1c36db6993290e7c41ca2b47c \
12+
# via execnet
913
arrow==0.12.1 \
1014
--hash=sha256:a558d3b7b6ce7ffc74206a86c147052de23d3d4ef0e17c210dd478c53575c4cd
1115
atomicwrites==1.2.1 \
@@ -57,12 +61,20 @@ coverage==4.5.1 \
5761
--hash=sha256:e05cb4d9aad6233d67e0541caa7e511fa4047ed7750ec2510d466e806e0255d6 \
5862
--hash=sha256:f05a636b4564104120111800021a92e43397bc12a5c72fed7036be8556e0029e \
5963
--hash=sha256:f3f501f345f24383c0000395b26b726e46758b71393267aeae0bd36f8b3ade80
64+
execnet==1.7.1 \
65+
--hash=sha256:cacb9df31c9680ec5f95553976c4da484d407e85e41c83cb812aa014f0eddc50 \
66+
--hash=sha256:d4efd397930c46415f62f8a31388d6be4f27a91d7550eb79bc64a756e0056547 \
67+
# via pytest-xdist
6068
flake8==3.6.0 \
6169
--hash=sha256:6a35f5b8761f45c5513e3405f110a86bea57982c3b75b766ce7b65217abe1670 \
6270
--hash=sha256:c01f8a3963b3571a8e6bd7a4063359aff90749e160778e03817cd9b71c9e07d2
6371
idna==2.7 \
6472
--hash=sha256:156a6814fb5ac1fc6850fb002e0852d56c0c8d2531923a51032d1b70760e186e \
6573
--hash=sha256:684a38a6f903c1d71d6d5fac066b58d7768af4de2b832e426ec79c30daa94a16
74+
importlib-metadata==0.23 \
75+
--hash=sha256:aa18d7378b00b40847790e7c27e11673d7fed219354109d0e7b9e5b25dc3ad26 \
76+
--hash=sha256:d5f18a79777f3aa179c145737780282e27b508fc8fd688cb17c7a813e8bd39af \
77+
# via pluggy, pytest
6678
mako==1.0.7 \
6779
--hash=sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae
6880
markupsafe==1.0 \
@@ -89,15 +101,19 @@ mypy==0.701 \
89101
--hash=sha256:bbf643528e2a55df2c1587008d6e3bda5c0445f1240dfa85129af22ae16d7a9a \
90102
--hash=sha256:c46ab3438bd21511db0f2c612d89d8344154c0c9494afc7fbc932de514cf8d15 \
91103
--hash=sha256:f7a83d6bd805855ef83ec605eb01ab4fa42bcef254b13631e451cbb44914a9b0
104+
packaging==19.2 \
105+
--hash=sha256:28b924174df7a2fa32c1953825ff29c61e2f5e082343165438812f00d3a7fc47 \
106+
--hash=sha256:d9551545c6d761f3def1677baf08ab2a3ca17c56879e70fecba2fc4dde4ed108 \
107+
# via pytest
92108
pathlib2==2.3.2 \
93109
--hash=sha256:8eb170f8d0d61825e09a95b38be068299ddeda82f35e96c3301a8a5e7604cb83 \
94110
--hash=sha256:d1aa2a11ba7b8f7b21ab852b1fb5afb277e1bb99d5dfc663380b5015c0d80c5a
95111
pip-tools==3.1.0 \
96112
--hash=sha256:31b43e5f8d605fc84f7506199025460abcb98a29d12cc99db268f73e39cf55e5 \
97113
--hash=sha256:b1ceca03b4a48346b2f6870565abb09d8d257d5b1524b4c6b222185bf26c3870
98-
pluggy==0.8.0 \
99-
--hash=sha256:447ba94990e8014ee25ec853339faf7b0fc8050cdc3289d4d71f7f410fb90095 \
100-
--hash=sha256:bde19360a8ec4dfd8a20dcb811780a30998101f078fc7ded6162f0076f50508f
114+
pluggy==0.13.0 \
115+
--hash=sha256:0db4b7601aae1d35b4a033282da476845aa19185c1e6964b25cf324b5e4ec3e6 \
116+
--hash=sha256:fa5fa1622fa6dd5c030e9cad086fa19ef6a0cf6d7a2d12318e10cb49d6d68f34
101117
py==1.7.0 \
102118
--hash=sha256:bf92637198836372b520efcba9e020c330123be8ce527e535d185ed4b6f45694 \
103119
--hash=sha256:e76826342cefe3c3d5f7e8ee4316b80d1dd8a300781612ddbc765c17ba25a6c6
@@ -107,23 +123,33 @@ pycodestyle==2.4.0 \
107123
pyflakes==2.0.0 \
108124
--hash=sha256:9a7662ec724d0120012f6e29d6248ae3727d821bba522a0e6b356eff19126a49 \
109125
--hash=sha256:f661252913bc1dbe7fcfcbf0af0db3f42ab65aabd1a6ca68fe5d466bace94dae
126+
pyparsing==2.4.2 \
127+
--hash=sha256:6f98a7b9397e206d78cc01df10131398f1c8b8510a2f4d97d9abd82e1aacdd80 \
128+
--hash=sha256:d9338df12903bbf5d65a0e4e87c2161968b10d2e489652bb47001d82a9b028b4 \
129+
# via packaging
110130
pyqt5==5.10.1 \
111131
--hash=sha256:1e652910bd1ffd23a3a48c510ecad23a57a853ed26b782cd54b16658e6f271ac \
112132
--hash=sha256:4db7113f464c733a99fcb66c4c093a47cf7204ad3f8b3bda502efcc0839ac14b \
113133
--hash=sha256:9c17ab3974c1fc7bbb04cc1c9dae780522c0ebc158613f3025fccae82227b5f7 \
114134
--hash=sha256:f6035baa009acf45e5f460cf88f73580ad5dc0e72330029acd99e477f20a5d61
115-
pytest-cov==2.6.0 \
116-
--hash=sha256:513c425e931a0344944f84ea47f3956be0e416d95acbd897a44970c8d926d5d7 \
117-
--hash=sha256:e360f048b7dae3f2f2a9a4d067b2dd6b6a015d384d1577c994a43f3f7cbad762
135+
pytest-cov==2.8.1 \
136+
--hash=sha256:cc6742d8bac45070217169f5f72ceee1e0e55b0221f54bcf24845972d3a47f2b \
137+
--hash=sha256:cdbdef4f870408ebdbfeb44e63e07eb18bb4619fae852f6e760645fa36172626
138+
pytest-forked==1.1.1 \
139+
--hash=sha256:e2d46f319c8063a3a0536b18f9cdea6eea3bc9fe2cb16c94e1d6fad3abc37300 \
140+
# via pytest-xdist
118141
pytest-mock==1.10.0 \
119142
--hash=sha256:53801e621223d34724926a5c98bd90e8e417ce35264365d39d6c896388dcc928 \
120143
--hash=sha256:d89a8209d722b8307b5e351496830d5cc5e192336003a485443ae9adeb7dd4c0
121144
pytest-random-order==1.0.0 \
122145
--hash=sha256:23881501819fdd03e7b6885b0aae83d212f5689851ded7b5ec2bdb00ad1c6c7f \
123146
--hash=sha256:7844b4c213bd18a3102dcc735010a0b44746801b97222d70bb4ea7d4ad535a43
124-
pytest==3.9.3 \
125-
--hash=sha256:a9e5e8d7ab9d5b0747f37740276eb362e6a76275d76cebbb52c6049d93b475db \
126-
--hash=sha256:bf47e8ed20d03764f963f0070ff1c8fda6e2671fc5dd562a4d3b7148ad60f5ca
147+
pytest-xdist==1.30.0 \
148+
--hash=sha256:5d1b1d4461518a6023d56dab62fb63670d6f7537f23e2708459a557329accf48 \
149+
--hash=sha256:a8569b027db70112b290911ce2ed732121876632fb3f40b1d39cd2f72f58b147
150+
pytest==5.2.1 \
151+
--hash=sha256:7e4800063ccfc306a53c461442526c5571e1462f61583506ce97e4da6a1d88c8 \
152+
--hash=sha256:ca563435f4941d0cb34767301c27bc65c510cb82e90b9ecf9cb52dc2c63caaa0
127153
python-dateutil==2.7.5 \
128154
--hash=sha256:063df5763652e21de43de7d9e00ccf239f953a832941e37be541614732cdfc93 \
129155
--hash=sha256:88f9287c0174266bb0d8cedd395cfba9c58e87e5ad86b2ce58859bc11be3cf02
@@ -132,8 +158,8 @@ python-editor==1.0.3 \
132158
requests==2.20.0 \
133159
--hash=sha256:99dcfdaaeb17caf6e526f32b6a7b780461512ab3f1d992187801694cba42770c \
134160
--hash=sha256:a84b8c9ab6239b578f22d1c21d51b696dcfe004032bb80ea832398d6909d7279
135-
securedrop-sdk==0.0.10 \
136-
--hash=sha256:07b9f9d91b26e2396ff5eb63b5e990ac969de57bbfb7c075d99ac5e269198cb0
161+
securedrop-sdk==0.0.11 \
162+
--hash=sha256:89a454a45eac15db702e06d24f5e4be64b8d033a5546aff056de762ecfc5f72a
137163
sip==4.19.8 \
138164
--hash=sha256:09f9a4e6c28afd0bafedb26ffba43375b97fe7207bd1a0d3513f79b7d168b331 \
139165
--hash=sha256:105edaaa1c8aa486662226360bd3999b4b89dd56de3e314d82b83ed0587d8783 \
@@ -176,7 +202,11 @@ typed-ast==1.3.4 \
176202
urllib3==1.24.3 \
177203
--hash=sha256:2393a695cd12afedd0dcb26fe5d50d0cf248e5a66f75dbd89a3d4eb333a61af4 \
178204
--hash=sha256:a637e5fae88995b256e3409dc4d52c2e2e0ba32c42a6365fee8bbd2238de3cfb
179-
180-
# WARNING: The following packages were not pinned, but pip requires them to be
181-
# pinned when the requirements file includes hashes. Consider using the --allow-unsafe flag.
182-
# setuptools==41.0.1 # via flake8, pytest
205+
wcwidth==0.1.7 \
206+
--hash=sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e \
207+
--hash=sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c \
208+
# via pytest
209+
zipp==0.6.0 \
210+
--hash=sha256:3718b1cbcd963c7d4c5511a8240812904164b7f381b647143a89d3b98f9bcd8e \
211+
--hash=sha256:f06903e9f1f43b12d371004b4ac7b06ab39a44adc747266928ae6debfa7b3335 \
212+
# via importlib-metadata

0 commit comments

Comments
 (0)