Compare commits
555 Commits
6.2.2
...
7.0.0.dev0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
109312ba86 | ||
|
|
2623ee2e0e | ||
|
|
ba1ad7d517 | ||
|
|
c4c3b6d4fd | ||
|
|
e729e0d1e6 | ||
|
|
c19f63d39d | ||
|
|
51742e14a1 | ||
|
|
6573107b97 | ||
|
|
ef395e1c38 | ||
|
|
f0e5640497 | ||
|
|
cb1dba0489 | ||
|
|
0d6cb3b281 | ||
|
|
d7b0e17205 | ||
|
|
942789bace | ||
|
|
f573b56bb6 | ||
|
|
e44300de7e | ||
|
|
8eb8c42bd6 | ||
|
|
ac10fe0679 | ||
|
|
0a6a1fa225 | ||
|
|
d2886b8d23 | ||
|
|
68b329dda8 | ||
|
|
ab3cd644dc | ||
|
|
a1967e9594 | ||
|
|
c4da6fff42 | ||
|
|
605fe29d12 | ||
|
|
ced125ad15 | ||
|
|
7eb0792cba | ||
|
|
6447ca5f1e | ||
|
|
5ea541d415 | ||
|
|
c675d8054d | ||
|
|
16685dc279 | ||
|
|
c85b21eaa0 | ||
|
|
fb7e36b2f7 | ||
|
|
c94766a580 | ||
|
|
85faaf8a1d | ||
|
|
5a9139c5ec | ||
|
|
b04aa015b9 | ||
|
|
657e35618f | ||
|
|
8010fb9f40 | ||
|
|
58036d463d | ||
|
|
992eabc29e | ||
|
|
479209bde1 | ||
|
|
68bb0db808 | ||
|
|
595b7e894c | ||
|
|
bce0ceafe4 | ||
|
|
50b166ff0b | ||
|
|
8300b266a8 | ||
|
|
7fb5a9d033 | ||
|
|
bb9683deea | ||
|
|
77235e2759 | ||
|
|
9ad726a9a0 | ||
|
|
cde6920e49 | ||
|
|
c51520ab2a | ||
|
|
360ce686f1 | ||
|
|
7ce69347ce | ||
|
|
788d8785ce | ||
|
|
cf7425d22b | ||
|
|
20f00997ff | ||
|
|
4b7d8b2edd | ||
|
|
43faea832d | ||
|
|
798bca4076 | ||
|
|
627b446252 | ||
|
|
640b2c0e13 | ||
|
|
1d5ee4dd7c | ||
|
|
1ba5b48565 | ||
|
|
1b5f5326d7 | ||
|
|
c5bf5f6fb0 | ||
|
|
ef9d01826a | ||
|
|
847d8f42ea | ||
|
|
e6ed28f0e7 | ||
|
|
9719237fe6 | ||
|
|
c0d525e44c | ||
|
|
88d84a5791 | ||
|
|
4a472952f7 | ||
|
|
538b5c2499 | ||
|
|
c90fdc684b | ||
|
|
11538e35e4 | ||
|
|
c198a7a67e | ||
|
|
ff6d29717c | ||
|
|
864a2bc0a3 | ||
|
|
6bc6ec323a | ||
|
|
e2567a680e | ||
|
|
d52cd08757 | ||
|
|
249c5b37dd | ||
|
|
0d502328ea | ||
|
|
53a74feea7 | ||
|
|
88944bec6a | ||
|
|
8872e8e7c7 | ||
|
|
eb7acba9e9 | ||
|
|
e59d0c461b | ||
|
|
3f414d7bbe | ||
|
|
dd8ad3fa9c | ||
|
|
06718da5d6 | ||
|
|
c73e354019 | ||
|
|
2414d23c78 | ||
|
|
24ad886b15 | ||
|
|
dbe66d97b4 | ||
|
|
b8f1b7cdc6 | ||
|
|
a69ed66c2e | ||
|
|
6ae71a2c2b | ||
|
|
8b2f83772d | ||
|
|
c516dba69a | ||
|
|
33c6ad5bf7 | ||
|
|
364bbe42fc | ||
|
|
c5de274136 | ||
|
|
850a844779 | ||
|
|
51293de324 | ||
|
|
0d6e3b7005 | ||
|
|
045ad5ac2d | ||
|
|
7cec85a37d | ||
|
|
b4cd14aae3 | ||
|
|
822624c252 | ||
|
|
0a07b71046 | ||
|
|
48f14c48ea | ||
|
|
c519dd64ed | ||
|
|
e0a3dc7bf8 | ||
|
|
7caf47acc6 | ||
|
|
337a729d95 | ||
|
|
6b53714d57 | ||
|
|
647ac4a79d | ||
|
|
3ae0103975 | ||
|
|
9e11d645b1 | ||
|
|
80acc0ed6f | ||
|
|
1e3fcece6d | ||
|
|
886fd70e2a | ||
|
|
124691122a | ||
|
|
113a860a1f | ||
|
|
4b6188b3b1 | ||
|
|
634312b14a | ||
|
|
245eefafcf | ||
|
|
adc197424d | ||
|
|
385988ca1a | ||
|
|
b7416f7abd | ||
|
|
a62a28b4b8 | ||
|
|
2534b7725e | ||
|
|
27564e7768 | ||
|
|
915ff7640b | ||
|
|
5ae2106059 | ||
|
|
3f71d63067 | ||
|
|
4fc67eea4f | ||
|
|
382599287f | ||
|
|
61be48b485 | ||
|
|
e354c5c919 | ||
|
|
710446420c | ||
|
|
f1570dc038 | ||
|
|
2637ec3921 | ||
|
|
4e048e0827 | ||
|
|
f772e5e2b3 | ||
|
|
9c4da3e7b6 | ||
|
|
f1a97512da | ||
|
|
9fa205290e | ||
|
|
8f49ffdb57 | ||
|
|
9d9b84d175 | ||
|
|
992c403fc8 | ||
|
|
2049ae271e | ||
|
|
f5c22a6b45 | ||
|
|
134d8f78d8 | ||
|
|
9ef608ef76 | ||
|
|
1e2c2d972d | ||
|
|
0d0e5ed74a | ||
|
|
ff24dfbc9f | ||
|
|
8d93f6ff0b | ||
|
|
11f6dc9de6 | ||
|
|
5a7be03285 | ||
|
|
0341893512 | ||
|
|
67af623d9e | ||
|
|
aead41e449 | ||
|
|
788d445b7b | ||
|
|
35c8139e09 | ||
|
|
c9e30a7035 | ||
|
|
0a75c8e57b | ||
|
|
f9d1fa4c4b | ||
|
|
4764c85275 | ||
|
|
c772d6d6a3 | ||
|
|
e5292ed8dc | ||
|
|
513247863a | ||
|
|
c7e146da0f | ||
|
|
7e82f6fc38 | ||
|
|
3cbbb0bb0d | ||
|
|
fbe66244b8 | ||
|
|
5d7fe91bd5 | ||
|
|
fb35851440 | ||
|
|
c117bc350e | ||
|
|
9078c3ce23 | ||
|
|
d2f3d40510 | ||
|
|
af31c60db1 | ||
|
|
8dd64622ca | ||
|
|
3c451751af | ||
|
|
6152135c29 | ||
|
|
d200598de9 | ||
|
|
4b214a6049 | ||
|
|
e3dc34ee41 | ||
|
|
22a17dba4e | ||
|
|
e14bd4a480 | ||
|
|
da66f00413 | ||
|
|
8be1628042 | ||
|
|
67d61e56e9 | ||
|
|
9653a0e9f4 | ||
|
|
047c9603f6 | ||
|
|
70daa279a7 | ||
|
|
207c07285f | ||
|
|
97a61916a6 | ||
|
|
41a90cd9fe | ||
|
|
b706a2c048 | ||
|
|
366c36a168 | ||
|
|
0b299044d1 | ||
|
|
43b547a1cb | ||
|
|
00f4cfe403 | ||
|
|
f3337c1854 | ||
|
|
5d2fad5362 | ||
|
|
07c6b3fb21 | ||
|
|
c49100cef8 | ||
|
|
1278f8b97e | ||
|
|
0dd1e5b4f4 | ||
|
|
78122a5304 | ||
|
|
aa10bff750 | ||
|
|
53ebe34ca2 | ||
|
|
deb5b5bd96 | ||
|
|
9c151a65c8 | ||
|
|
778d2b2499 | ||
|
|
0061ec5555 | ||
|
|
b96e229c95 | ||
|
|
bad1963697 | ||
|
|
ca4a7a085e | ||
|
|
bfdfab00dd | ||
|
|
9052a9e313 | ||
|
|
c1bdff9e69 | ||
|
|
a7416a535a | ||
|
|
913cffa45f | ||
|
|
b2954e85d6 | ||
|
|
878a51ef53 | ||
|
|
d9f4cedf17 | ||
|
|
8c65a4f174 | ||
|
|
ddbc00d61e | ||
|
|
c1e057065c | ||
|
|
be8d63e33b | ||
|
|
9e8a6b6eeb | ||
|
|
76ab94e4a0 | ||
|
|
8d21df0dc6 | ||
|
|
7dfaaa1e16 | ||
|
|
f28421cc70 | ||
|
|
a7d528e058 | ||
|
|
a6cf0a0a0e | ||
|
|
bc055e8e69 | ||
|
|
42ece0ca81 | ||
|
|
3add1a4d0f | ||
|
|
7ac7610089 | ||
|
|
4ddf6c647c | ||
|
|
2994022753 | ||
|
|
a550db4b6c | ||
|
|
945cc0b5a1 | ||
|
|
30f1b81eb2 | ||
|
|
ff6d5ae278 | ||
|
|
35df3e68d5 | ||
|
|
fb481c7e6f | ||
|
|
4690e4c510 | ||
|
|
202dd9f423 | ||
|
|
ccdadb64ea | ||
|
|
6a174afdfe | ||
|
|
e515264eb1 | ||
|
|
fe215bda6b | ||
|
|
f7efb9a01c | ||
|
|
6071b2c647 | ||
|
|
dd3709718d | ||
|
|
6ab461f460 | ||
|
|
da4abd1c82 | ||
|
|
43b451e95e | ||
|
|
1f131afb07 | ||
|
|
2ce446a75f | ||
|
|
7781582d52 | ||
|
|
c83b05af6b | ||
|
|
584fd0f387 | ||
|
|
f0c7043138 | ||
|
|
a03ee02817 | ||
|
|
b26d1bb18f | ||
|
|
2641761c1c | ||
|
|
64107be443 | ||
|
|
d171a3f52d | ||
|
|
63bc49de70 | ||
|
|
59251e8a2a | ||
|
|
cdbeb03aef | ||
|
|
493b54e21e | ||
|
|
ba0193ad06 | ||
|
|
3075078498 | ||
|
|
ba7bd3d77c | ||
|
|
8c350b9837 | ||
|
|
ef1308c23b | ||
|
|
db539ed2b0 | ||
|
|
9fa6673222 | ||
|
|
af9f27a874 | ||
|
|
f2d65c85f4 | ||
|
|
96ef7d678b | ||
|
|
5bbfb4e058 | ||
|
|
dd576509e1 | ||
|
|
146eda93e7 | ||
|
|
639c4e64a1 | ||
|
|
843e9eac2c | ||
|
|
8410d9ac54 | ||
|
|
ff2ee96b8c | ||
|
|
32ad70dea8 | ||
|
|
d8695410a4 | ||
|
|
4b7edef08f | ||
|
|
a362200d47 | ||
|
|
2a789b9e3a | ||
|
|
c9867bcc9d | ||
|
|
ce2ad8ebd4 | ||
|
|
d2d975d6cf | ||
|
|
4a19533ba5 | ||
|
|
bfbf733a3e | ||
|
|
dbed1ff68f | ||
|
|
38d8deb74d | ||
|
|
7a6ec5616d | ||
|
|
ddde3266c6 | ||
|
|
125633728f | ||
|
|
79b03ce8db | ||
|
|
fc651fb158 | ||
|
|
412fc001a0 | ||
|
|
f0ad73c4b0 | ||
|
|
620e819656 | ||
|
|
77cb110258 | ||
|
|
22dad53a24 | ||
|
|
7c792e96c6 | ||
|
|
19a2f7425d | ||
|
|
6e7dc8bac8 | ||
|
|
c14a9adba3 | ||
|
|
4dbb29431a | ||
|
|
bc0af99e5e | ||
|
|
284b9dba9d | ||
|
|
decca74788 | ||
|
|
897b5a3bd6 | ||
|
|
62ef875796 | ||
|
|
cd783eba03 | ||
|
|
a623b1b086 | ||
|
|
22c0dace3b | ||
|
|
b7f2d7ca61 | ||
|
|
514f8e0680 | ||
|
|
bbea18d7f9 | ||
|
|
690fb26ec7 | ||
|
|
9d09d19911 | ||
|
|
3b7fc2c9c8 | ||
|
|
54a154c86f | ||
|
|
d6522b517b | ||
|
|
d37fe13af5 | ||
|
|
d76f7b3039 | ||
|
|
e503e27579 | ||
|
|
060cbef260 | ||
|
|
c9bb4c418f | ||
|
|
56421aed01 | ||
|
|
09d4c5e30a | ||
|
|
0e5e4e03e6 | ||
|
|
4964b468c8 | ||
|
|
e6012612b9 | ||
|
|
a44dcf5ece | ||
|
|
565fe0fb7d | ||
|
|
c9d623971a | ||
|
|
532543b4ef | ||
|
|
ab2eb94054 | ||
|
|
a0ae5fd652 | ||
|
|
16e21c22a3 | ||
|
|
3d831225bb | ||
|
|
92959fe236 | ||
|
|
6432fc2302 | ||
|
|
1003beaffa | ||
|
|
f85427b92a | ||
|
|
e9d554c5f5 | ||
|
|
7b91302b33 | ||
|
|
ee5afb2a8f | ||
|
|
ef14f286a3 | ||
|
|
e8d7a7b843 | ||
|
|
325d701f6e | ||
|
|
3c6bd7eb27 | ||
|
|
5822888d73 | ||
|
|
f42b68ccaa | ||
|
|
f674f6da9f | ||
|
|
bcfe253f5b | ||
|
|
150bdceb7a | ||
|
|
c604f3f0c5 | ||
|
|
ed8cabe4fd | ||
|
|
e3c0fd3203 | ||
|
|
375e95180c | ||
|
|
16af1a31fd | ||
|
|
b3115c1b06 | ||
|
|
d358a060ad | ||
|
|
80c223474c | ||
|
|
bebb6953eb | ||
|
|
709c211e68 | ||
|
|
97cfd66806 | ||
|
|
287bab09a4 | ||
|
|
7c622d7462 | ||
|
|
b77f071bef | ||
|
|
3907856cb3 | ||
|
|
1d895dd46c | ||
|
|
298541f540 | ||
|
|
100c8deab5 | ||
|
|
275174e147 | ||
|
|
3568df22b0 | ||
|
|
3165b1e323 | ||
|
|
c26dddc651 | ||
|
|
1b2ca22e9b | ||
|
|
5c61d60b0d | ||
|
|
ed8f424bcb | ||
|
|
c971f2f474 | ||
|
|
de06f468ed | ||
|
|
f0f19aa8d9 | ||
|
|
38a3e30cd9 | ||
|
|
afea190797 | ||
|
|
07f0eb26b4 | ||
|
|
63ea727bc2 | ||
|
|
beda7a8a31 | ||
|
|
0b510bcc51 | ||
|
|
6a5d47a243 | ||
|
|
7b4ee65bdc | ||
|
|
0365b1be64 | ||
|
|
56cea26445 | ||
|
|
0939c3e022 | ||
|
|
8bb3977cb6 | ||
|
|
dfe933cdb4 | ||
|
|
6806091b93 | ||
|
|
33861098d9 | ||
|
|
781b73bb52 | ||
|
|
f3efc4e049 | ||
|
|
2a890286f8 | ||
|
|
fff9f28fdd | ||
|
|
5cc295e74b | ||
|
|
83ee1a1f3b | ||
|
|
48fb989a71 | ||
|
|
d5df8f99ab | ||
|
|
c30feeef8b | ||
|
|
0d19aff562 | ||
|
|
1db78bec31 | ||
|
|
03c3a90c68 | ||
|
|
960ebae943 | ||
|
|
6db082a448 | ||
|
|
637300d13d | ||
|
|
c83d030028 | ||
|
|
0d4121d24b | ||
|
|
bb3d43c9a6 | ||
|
|
14d71b2c22 | ||
|
|
d1fcd425a3 | ||
|
|
2b14edb108 | ||
|
|
ceb4d6f6d5 | ||
|
|
5f4e55fb6d | ||
|
|
42ae8180dd | ||
|
|
410622f719 | ||
|
|
f7b0b1dd1f | ||
|
|
da70f61f67 | ||
|
|
d4f8e4b40c | ||
|
|
adc0f29b8f | ||
|
|
bda9ce4e0f | ||
|
|
eef2d1a8e2 | ||
|
|
9ba1821e91 | ||
|
|
7f782c72ba | ||
|
|
a9e43152bc | ||
|
|
c9e9a599fe | ||
|
|
25e657bfc1 | ||
|
|
7f989203ed | ||
|
|
3dde519f53 | ||
|
|
096bae6c68 | ||
|
|
addbd3161e | ||
|
|
42d5545f42 | ||
|
|
7a5a6cb51c | ||
|
|
203a9b3ab2 | ||
|
|
cfa0c3b0d9 | ||
|
|
af78efc7fa | ||
|
|
f6529fd3a1 | ||
|
|
80c33c8178 | ||
|
|
78fb97105f | ||
|
|
31ae4e1764 | ||
|
|
65b8391ead | ||
|
|
329fff69a3 | ||
|
|
5336ba28cc | ||
|
|
8e00df4c4b | ||
|
|
8d16bec329 | ||
|
|
14b5f5e528 | ||
|
|
2ff88098a7 | ||
|
|
8ee6d0a866 | ||
|
|
ade253c790 | ||
|
|
6c575ad8c8 | ||
|
|
b02f1c8ae7 | ||
|
|
bbd22e1769 | ||
|
|
ac428f67eb | ||
|
|
20c59e3aa4 | ||
|
|
73c4105230 | ||
|
|
7d306e9e86 | ||
|
|
5f11a35b99 | ||
|
|
48c9a96a03 | ||
|
|
7585221d55 | ||
|
|
ee03e31831 | ||
|
|
7751904875 | ||
|
|
e772f02d15 | ||
|
|
bf9b59b3c8 | ||
|
|
8550c29180 | ||
|
|
96ea867fec | ||
|
|
bd76042344 | ||
|
|
6d3a66d947 | ||
|
|
d8d2df7e6f | ||
|
|
da01ee0a4b | ||
|
|
af5da977e3 | ||
|
|
35d6a7e78e | ||
|
|
5e323becb7 | ||
|
|
ca4effc822 | ||
|
|
4faed28261 | ||
|
|
a218413008 | ||
|
|
170a2c5040 | ||
|
|
8b220fad4d | ||
|
|
92ba96b061 | ||
|
|
813ce45985 | ||
|
|
d64706c33d | ||
|
|
1839713b71 | ||
|
|
6aa4d1c7ab | ||
|
|
69c302479e | ||
|
|
2ec372df8b | ||
|
|
7aa2240832 | ||
|
|
042d12fae6 | ||
|
|
2c05a7babb | ||
|
|
73586be08f | ||
|
|
89dcfbf293 | ||
|
|
196b173c8a | ||
|
|
15156e94c4 | ||
|
|
f14ab08de3 | ||
|
|
293a7c962d | ||
|
|
4da445dc2e | ||
|
|
403424d60b | ||
|
|
1264404fe7 | ||
|
|
bd894e3065 | ||
|
|
ce206ae462 | ||
|
|
3eef150f2e | ||
|
|
02e69e5cdc | ||
|
|
8255effc5b | ||
|
|
534d174fd2 | ||
|
|
cab16f3aac | ||
|
|
a1c5111a40 | ||
|
|
f1a1de2257 | ||
|
|
d46ecbc18b | ||
|
|
950fbbc326 | ||
|
|
56600414df | ||
|
|
9ccbf5b899 | ||
|
|
6c899a0afa | ||
|
|
8eef8c6004 | ||
|
|
592b32bd69 | ||
|
|
2cb34a99cb | ||
|
|
cb8142b8ec | ||
|
|
382cb2aae1 | ||
|
|
a09d8b1599 | ||
|
|
92b444a914 | ||
|
|
ad65e816e4 | ||
|
|
4ed9a38519 | ||
|
|
7e2e6630ad | ||
|
|
fa784e1436 | ||
|
|
28588bf535 | ||
|
|
37b154b1ec | ||
|
|
09582048be | ||
|
|
54a7356a9f | ||
|
|
ed658d6829 | ||
|
|
572dfcd160 |
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -13,7 +13,7 @@ If this change fixes an issue, please:
|
||||
|
||||
Unless your change is trivial or a small documentation fix (e.g., a typo or reword of a small section) please:
|
||||
|
||||
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/master/changelog/README.rst) for details.
|
||||
- [ ] Create a new changelog file in the `changelog` folder, with a name like `<ISSUE NUMBER>.<TYPE>.rst`. See [changelog/README.rst](https://github.com/pytest-dev/pytest/blob/main/changelog/README.rst) for details.
|
||||
|
||||
Write sentences in the **past or present tense**, examples:
|
||||
|
||||
|
||||
73
.github/workflows/main.yml
vendored
73
.github/workflows/main.yml
vendored
@@ -3,7 +3,7 @@ name: main
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- "[0-9]+.[0-9]+.x"
|
||||
tags:
|
||||
- "[0-9]+.[0-9]+.[0-9]+"
|
||||
@@ -11,13 +11,21 @@ on:
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- main
|
||||
- "[0-9]+.[0-9]+.x"
|
||||
|
||||
env:
|
||||
PYTEST_ADDOPTS: "--color=yes"
|
||||
|
||||
# Set permissions at the job level.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
@@ -27,6 +35,8 @@ jobs:
|
||||
"windows-py37",
|
||||
"windows-py37-pluggy",
|
||||
"windows-py38",
|
||||
"windows-py39",
|
||||
"windows-py310",
|
||||
|
||||
"ubuntu-py36",
|
||||
"ubuntu-py37",
|
||||
@@ -34,6 +44,7 @@ jobs:
|
||||
"ubuntu-py37-freeze",
|
||||
"ubuntu-py38",
|
||||
"ubuntu-py39",
|
||||
"ubuntu-py310",
|
||||
"ubuntu-pypy3",
|
||||
|
||||
"macos-py37",
|
||||
@@ -56,12 +67,20 @@ jobs:
|
||||
- name: "windows-py37-pluggy"
|
||||
python: "3.7"
|
||||
os: windows-latest
|
||||
tox_env: "py37-pluggymaster-xdist"
|
||||
tox_env: "py37-pluggymain-xdist"
|
||||
- name: "windows-py38"
|
||||
python: "3.8"
|
||||
os: windows-latest
|
||||
tox_env: "py38-unittestextras"
|
||||
use_coverage: true
|
||||
- name: "windows-py39"
|
||||
python: "3.9"
|
||||
os: windows-latest
|
||||
tox_env: "py39-xdist"
|
||||
- name: "windows-py310"
|
||||
python: "3.10-dev"
|
||||
os: windows-latest
|
||||
tox_env: "py310-xdist"
|
||||
|
||||
- name: "ubuntu-py36"
|
||||
python: "3.6"
|
||||
@@ -75,7 +94,7 @@ jobs:
|
||||
- name: "ubuntu-py37-pluggy"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py37-pluggymaster-xdist"
|
||||
tox_env: "py37-pluggymain-xdist"
|
||||
- name: "ubuntu-py37-freeze"
|
||||
python: "3.7"
|
||||
os: ubuntu-latest
|
||||
@@ -88,8 +107,12 @@ jobs:
|
||||
python: "3.9"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py39-xdist"
|
||||
- name: "ubuntu-py310"
|
||||
python: "3.10-dev"
|
||||
os: ubuntu-latest
|
||||
tox_env: "py310-xdist"
|
||||
- name: "ubuntu-pypy3"
|
||||
python: "pypy3"
|
||||
python: "pypy-3.7"
|
||||
os: ubuntu-latest
|
||||
tox_env: "pypy3-xdist"
|
||||
|
||||
@@ -122,10 +145,13 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python ${{ matrix.python }}
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -137,38 +163,39 @@ jobs:
|
||||
|
||||
- name: Test with coverage
|
||||
if: "matrix.use_coverage"
|
||||
env:
|
||||
_PYTEST_TOX_COVERAGE_RUN: "coverage run -m"
|
||||
COVERAGE_PROCESS_START: ".coveragerc"
|
||||
_PYTEST_TOX_EXTRA_DEP: "coverage-enable-subprocess"
|
||||
run: "tox -e ${{ matrix.tox_env }}"
|
||||
run: "tox -e ${{ matrix.tox_env }}-coverage"
|
||||
|
||||
- name: Prepare coverage token
|
||||
if: (matrix.use_coverage && ( github.repository == 'pytest-dev/pytest' || github.event_name == 'pull_request' ))
|
||||
run: |
|
||||
python scripts/append_codecov_token.py
|
||||
|
||||
- name: Report coverage
|
||||
if: (matrix.use_coverage)
|
||||
- name: Upload coverage
|
||||
if: matrix.use_coverage && github.repository == 'pytest-dev/pytest'
|
||||
env:
|
||||
CODECOV_NAME: ${{ matrix.name }}
|
||||
run: bash scripts/report-coverage.sh -F GHA,${{ runner.os }}
|
||||
run: bash scripts/upload-coverage.sh -F GHA,${{ runner.os }}
|
||||
|
||||
linting:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
|
||||
- name: set PY
|
||||
run: echo "name=PY::$(python -c 'import hashlib, sys;print(hashlib.sha256(sys.version.encode()+sys.executable.encode()).hexdigest())')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install tox
|
||||
|
||||
- run: tox -e linting
|
||||
|
||||
deploy:
|
||||
@@ -176,6 +203,8 @@ jobs:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
needs: [build]
|
||||
|
||||
@@ -183,25 +212,31 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.7"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade wheel setuptools tox
|
||||
|
||||
- name: Build package
|
||||
run: |
|
||||
python setup.py sdist bdist_wheel
|
||||
|
||||
- name: Publish package to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@master
|
||||
with:
|
||||
user: __token__
|
||||
password: ${{ secrets.pypi_token }}
|
||||
|
||||
- name: Publish GitHub release notes
|
||||
env:
|
||||
GH_RELEASE_NOTES_TOKEN: ${{ secrets.release_notes }}
|
||||
GH_RELEASE_NOTES_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
sudo apt-get install pandoc
|
||||
tox -e publish-gh-release-notes
|
||||
|
||||
53
.github/workflows/prepare-release-pr.yml
vendored
Normal file
53
.github/workflows/prepare-release-pr.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
name: prepare release pr
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
branch:
|
||||
description: 'Branch to base the release from'
|
||||
required: true
|
||||
default: ''
|
||||
major:
|
||||
description: 'Major release? (yes/no)'
|
||||
required: true
|
||||
default: 'no'
|
||||
prerelease:
|
||||
description: 'Prerelease (ex: rc1). Leave empty if not a pre-release.'
|
||||
required: true
|
||||
default: ''
|
||||
|
||||
# Set permissions at the job level.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.8"
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade setuptools tox
|
||||
|
||||
- name: Prepare release PR (minor/patch release)
|
||||
if: github.event.inputs.major == 'no'
|
||||
run: |
|
||||
tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --prerelease '${{ github.event.inputs.prerelease }}'
|
||||
|
||||
- name: Prepare release PR (major release)
|
||||
if: github.event.inputs.major == 'yes'
|
||||
run: |
|
||||
tox -e prepare-release-pr -- ${{ github.event.inputs.branch }} ${{ github.token }} --major --prerelease '${{ github.event.inputs.prerelease }}'
|
||||
31
.github/workflows/release-on-comment.yml
vendored
31
.github/workflows/release-on-comment.yml
vendored
@@ -1,31 +0,0 @@
|
||||
# part of our release process, see `release-on-comment.py`
|
||||
name: release on comment
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, edited]
|
||||
issue_comment:
|
||||
types: [created, edited]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
if: (github.event.comment && startsWith(github.event.comment.body, '@pytestbot please')) || (github.event.issue && !github.event.comment && startsWith(github.event.issue.body, '@pytestbot please'))
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: "3.8"
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade setuptools tox
|
||||
- name: Prepare release
|
||||
run: |
|
||||
tox -e release-on-comment -- $GITHUB_EVENT_PATH ${{ secrets.chatops }}
|
||||
48
.github/workflows/update-plugin-list.yml
vendored
Normal file
48
.github/workflows/update-plugin-list.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
name: Update Plugin List
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# At 00:00 on Sunday.
|
||||
# https://crontab.guru
|
||||
- cron: '0 0 * * 0'
|
||||
workflow_dispatch:
|
||||
|
||||
# Set permissions at the job level.
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
createPullRequest:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.8
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install packaging requests tabulate[widechars]
|
||||
|
||||
- name: Update Plugin List
|
||||
run: python scripts/update-plugin-list.py
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@2455e1596942c2902952003bbb574afbbe2ab2e6
|
||||
with:
|
||||
commit-message: '[automated] Update plugin list'
|
||||
author: 'pytest bot <pytestbot@users.noreply.github.com>'
|
||||
branch: update-plugin-list/patch
|
||||
delete-branch: true
|
||||
branch-suffix: short-commit-hash
|
||||
title: '[automated] Update plugin list'
|
||||
body: '[automated] Update plugin list'
|
||||
@@ -1,16 +1,16 @@
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 19.10b0
|
||||
rev: 21.6b0
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--safe, --quiet]
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: v1.8.0
|
||||
rev: v1.10.0
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies: [black==19.10b0]
|
||||
additional_dependencies: [black==20.8b1]
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
rev: v4.0.1
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
@@ -20,8 +20,8 @@ repos:
|
||||
- id: debug-statements
|
||||
exclude: _pytest/(debugging|hookspec).py
|
||||
language_version: python3
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.8.3
|
||||
- repo: https://github.com/PyCQA/flake8
|
||||
rev: 3.9.2
|
||||
hooks:
|
||||
- id: flake8
|
||||
language_version: python3
|
||||
@@ -29,27 +29,26 @@ repos:
|
||||
- flake8-typing-imports==1.9.0
|
||||
- flake8-docstrings==1.5.0
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v2.3.5
|
||||
rev: v2.5.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ['--application-directories=.:src', --py36-plus]
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v2.7.2
|
||||
rev: v2.19.4
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--py36-plus]
|
||||
- repo: https://github.com/asottile/setup-cfg-fmt
|
||||
rev: v1.11.0
|
||||
rev: v1.17.0
|
||||
hooks:
|
||||
- id: setup-cfg-fmt
|
||||
# TODO: when upgrading setup-cfg-fmt this can be removed
|
||||
args: [--max-py-version=3.9]
|
||||
args: [--max-py-version=3.10]
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.6.0
|
||||
rev: v1.9.0
|
||||
hooks:
|
||||
- id: python-use-type-annotations
|
||||
- repo: https://github.com/pre-commit/mirrors-mypy
|
||||
rev: v0.790
|
||||
rev: v0.902
|
||||
hooks:
|
||||
- id: mypy
|
||||
files: ^(src/|testing/)
|
||||
@@ -59,6 +58,8 @@ repos:
|
||||
- py>=1.8.2
|
||||
- attrs>=19.2.0
|
||||
- packaging
|
||||
- types-toml
|
||||
- types-pkg_resources
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: rst
|
||||
@@ -89,3 +90,9 @@ repos:
|
||||
xml\.
|
||||
)
|
||||
types: [python]
|
||||
- id: py-path-deprecated
|
||||
name: py.path usage is deprecated
|
||||
exclude: docs|src/_pytest/deprecated.py|testing/deprecated_test.py
|
||||
language: pygrep
|
||||
entry: \bpy\.path\.local
|
||||
types: [python]
|
||||
|
||||
14
AUTHORS
14
AUTHORS
@@ -5,6 +5,7 @@ Contributors include::
|
||||
|
||||
Aaron Coleman
|
||||
Abdeali JK
|
||||
Abdelrahman Elbehery
|
||||
Abhijeet Kasurde
|
||||
Adam Johnson
|
||||
Adam Uhlir
|
||||
@@ -23,6 +24,7 @@ Andras Tim
|
||||
Andrea Cimatoribus
|
||||
Andreas Motl
|
||||
Andreas Zeidler
|
||||
Andrew Shapton
|
||||
Andrey Paramonov
|
||||
Andrzej Klajnert
|
||||
Andrzej Ostrowski
|
||||
@@ -30,6 +32,7 @@ Andy Freeland
|
||||
Anthon van der Neut
|
||||
Anthony Shaw
|
||||
Anthony Sottile
|
||||
Anton Grinevich
|
||||
Anton Lodder
|
||||
Antony Lee
|
||||
Arel Cordero
|
||||
@@ -40,6 +43,7 @@ Aron Curzon
|
||||
Aviral Verma
|
||||
Aviv Palivoda
|
||||
Barney Gale
|
||||
Ben Gartner
|
||||
Ben Webb
|
||||
Benjamin Peterson
|
||||
Bernard Pratz
|
||||
@@ -58,6 +62,7 @@ Charles Machalow
|
||||
Charnjit SiNGH (CCSJ)
|
||||
Chris Lamb
|
||||
Chris NeJame
|
||||
Chris Rose
|
||||
Christian Boelsen
|
||||
Christian Fetzer
|
||||
Christian Neumüller
|
||||
@@ -76,6 +81,7 @@ Daniel Grana
|
||||
Daniel Hahler
|
||||
Daniel Nuri
|
||||
Daniel Wandschneider
|
||||
Daniele Procida
|
||||
Danielle Jenkins
|
||||
Daniil Galiev
|
||||
Dave Hunt
|
||||
@@ -95,6 +101,7 @@ Dominic Mortlock
|
||||
Duncan Betts
|
||||
Edison Gustavo Muenz
|
||||
Edoardo Batini
|
||||
Edson Tadeu M. Manoel
|
||||
Eduardo Schettino
|
||||
Eli Boyarski
|
||||
Elizaveta Shashkova
|
||||
@@ -137,6 +144,7 @@ Iwan Briquemont
|
||||
Jaap Broekhuizen
|
||||
Jakob van Santen
|
||||
Jakub Mitoraj
|
||||
James Bourbeau
|
||||
Jan Balster
|
||||
Janne Vanhala
|
||||
Jason R. Coombs
|
||||
@@ -157,6 +165,7 @@ Josh Karpel
|
||||
Joshua Bronson
|
||||
Jurko Gospodnetić
|
||||
Justyna Janczyszyn
|
||||
Justice Ndou
|
||||
Kale Kundert
|
||||
Kamran Ahmad
|
||||
Karl O. Pinc
|
||||
@@ -224,6 +233,7 @@ Nicholas Murphy
|
||||
Niclas Olofsson
|
||||
Nicolas Delaby
|
||||
Nikolay Kondratyev
|
||||
Olga Matoula
|
||||
Oleg Pidsadnyi
|
||||
Oleg Sushchenko
|
||||
Oliver Bestwalter
|
||||
@@ -231,6 +241,7 @@ Omar Kohl
|
||||
Omer Hadari
|
||||
Ondřej Súkup
|
||||
Oscar Benjamin
|
||||
Parth Patel
|
||||
Patrick Hayes
|
||||
Pauli Virtanen
|
||||
Pavel Karateev
|
||||
@@ -265,6 +276,7 @@ Ross Lawley
|
||||
Ruaridh Williamson
|
||||
Russel Winder
|
||||
Ryan Wooden
|
||||
Saiprasad Kale
|
||||
Samuel Dion-Girardeau
|
||||
Samuel Searles-Bryant
|
||||
Samuele Pedroni
|
||||
@@ -273,6 +285,7 @@ Sankt Petersbug
|
||||
Segev Finer
|
||||
Serhii Mozghovyi
|
||||
Seth Junot
|
||||
Shantanu Jain
|
||||
Shubham Adep
|
||||
Simon Gomizelj
|
||||
Simon Kerr
|
||||
@@ -324,5 +337,6 @@ Xuan Luong
|
||||
Xuecong Liao
|
||||
Yoav Caspi
|
||||
Zac Hatfield-Dodds
|
||||
Zachary Kneupper
|
||||
Zoltán Máté
|
||||
Zsolt Cserna
|
||||
|
||||
@@ -4,4 +4,4 @@ Changelog
|
||||
|
||||
The pytest CHANGELOG is located `here <https://docs.pytest.org/en/stable/changelog.html>`__.
|
||||
|
||||
The source document can be found at: https://github.com/pytest-dev/pytest/blob/master/doc/en/changelog.rst
|
||||
The source document can be found at: https://github.com/pytest-dev/pytest/blob/main/doc/en/changelog.rst
|
||||
|
||||
@@ -160,7 +160,7 @@ the following:
|
||||
|
||||
- an issue tracker for bug reports and enhancement requests.
|
||||
|
||||
- a `changelog <http://keepachangelog.com/>`_.
|
||||
- a `changelog <https://keepachangelog.com/>`_.
|
||||
|
||||
If no contributor strongly objects and two agree, the repository can then be
|
||||
transferred to the ``pytest-dev`` organisation.
|
||||
@@ -234,9 +234,9 @@ Here is a simple overview, with pytest-specific bits:
|
||||
|
||||
$ git clone git@github.com:YOUR_GITHUB_USERNAME/pytest.git
|
||||
$ cd pytest
|
||||
# now, create your own branch off "master":
|
||||
# now, create your own branch off "main":
|
||||
|
||||
$ git checkout -b your-bugfix-branch-name master
|
||||
$ git checkout -b your-bugfix-branch-name main
|
||||
|
||||
Given we have "major.minor.micro" version numbers, bug fixes will usually
|
||||
be released in micro releases whereas features will be released in
|
||||
@@ -259,7 +259,7 @@ Here is a simple overview, with pytest-specific bits:
|
||||
|
||||
Tox is used to run all the tests and will automatically setup virtualenvs
|
||||
to run the tests in.
|
||||
(will implicitly use http://www.virtualenv.org/en/latest/)::
|
||||
(will implicitly use https://virtualenv.pypa.io/en/latest/)::
|
||||
|
||||
$ pip install tox
|
||||
|
||||
@@ -318,26 +318,26 @@ Here is a simple overview, with pytest-specific bits:
|
||||
compare: your-branch-name
|
||||
|
||||
base-fork: pytest-dev/pytest
|
||||
base: master
|
||||
base: main
|
||||
|
||||
|
||||
Writing Tests
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Writing tests for plugins or for pytest itself is often done using the `testdir fixture <https://docs.pytest.org/en/stable/reference.html#testdir>`_, as a "black-box" test.
|
||||
Writing tests for plugins or for pytest itself is often done using the `pytester fixture <https://docs.pytest.org/en/stable/reference.html#pytester>`_, as a "black-box" test.
|
||||
|
||||
For example, to ensure a simple test passes you can write:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
def test_true_assertion(pytester):
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert True
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result = pytester.runpytest()
|
||||
result.assert_outcomes(failed=0, passed=1)
|
||||
|
||||
|
||||
@@ -346,14 +346,14 @@ Alternatively, it is possible to make checks based on the actual output of the t
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_true_assertion(testdir):
|
||||
testdir.makepyfile(
|
||||
def test_true_assertion(pytester):
|
||||
pytester.makepyfile(
|
||||
"""
|
||||
def test_foo():
|
||||
assert False
|
||||
"""
|
||||
)
|
||||
result = testdir.runpytest()
|
||||
result = pytester.runpytest()
|
||||
result.stdout.fnmatch_lines(["*assert False*", "*1 failed*"])
|
||||
|
||||
When choosing a file where to write a new test, take a look at the existing files and see if there's
|
||||
@@ -387,15 +387,15 @@ Suppose for example that the latest release was 1.2.3, and you want to include
|
||||
a bug fix in 1.2.4 (check https://github.com/pytest-dev/pytest/releases for the
|
||||
actual latest release). The procedure for this is:
|
||||
|
||||
#. First, make sure the bug is fixed the ``master`` branch, with a regular pull
|
||||
#. First, make sure the bug is fixed the ``main`` branch, with a regular pull
|
||||
request, as described above. An exception to this is if the bug fix is not
|
||||
applicable to ``master`` anymore.
|
||||
applicable to ``main`` anymore.
|
||||
|
||||
#. ``git checkout origin/1.2.x -b backport-XXXX`` # use the master PR number here
|
||||
#. ``git checkout origin/1.2.x -b backport-XXXX`` # use the main PR number here
|
||||
|
||||
#. Locate the merge commit on the PR, in the *merged* message, for example:
|
||||
|
||||
nicoddemus merged commit 0f8b462 into pytest-dev:master
|
||||
nicoddemus merged commit 0f8b462 into pytest-dev:main
|
||||
|
||||
#. ``git cherry-pick -x -m1 REVISION`` # use the revision you found above (``0f8b462``).
|
||||
|
||||
@@ -408,8 +408,8 @@ actual latest release). The procedure for this is:
|
||||
Who does the backporting
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As mentioned above, bugs should first be fixed on ``master`` (except in rare occasions
|
||||
that a bug only happens in a previous release). So who should do the backport procedure described
|
||||
As mentioned above, bugs should first be fixed on ``main`` (except in rare occasions
|
||||
that a bug only happens in a previous release). So, who should do the backport procedure described
|
||||
above?
|
||||
|
||||
1. If the bug was fixed by a core developer, it is the main responsibility of that core developer
|
||||
@@ -417,8 +417,8 @@ above?
|
||||
2. However, often the merge is done by another maintainer, in which case it is nice of them to
|
||||
do the backport procedure if they have the time.
|
||||
3. For bugs submitted by non-maintainers, it is expected that a core developer will to do
|
||||
the backport, normally the one that merged the PR on ``master``.
|
||||
4. If a non-maintainers notices a bug which is fixed on ``master`` but has not been backported
|
||||
the backport, normally the one that merged the PR on ``main``.
|
||||
4. If a non-maintainers notices a bug which is fixed on ``main`` but has not been backported
|
||||
(due to maintainers forgetting to apply the *needs backport* label, or just plain missing it),
|
||||
they are also welcome to open a PR with the backport. The procedure is simple and really
|
||||
helps with the maintenance of the project.
|
||||
@@ -447,7 +447,7 @@ can always reopen the issue/pull request in their own time later if it makes sen
|
||||
When to close
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Here are a few general rules the maintainers use to decide when to close issues/PRs because
|
||||
Here are a few general rules the maintainers use deciding when to close issues/PRs because
|
||||
of lack of inactivity:
|
||||
|
||||
* Issues labeled ``question`` or ``needs information``: closed after 14 days inactive.
|
||||
@@ -459,15 +459,15 @@ The above are **not hard rules**, but merely **guidelines**, and can be (and oft
|
||||
Closing pull requests
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When closing a Pull Request, it needs to be acknowledge the time, effort, and interest demonstrated by the person which submitted it. As mentioned previously, it is not the intent of the team to dismiss stalled pull request entirely but to merely to clear up our queue, so a message like the one below is warranted when closing a pull request that went stale:
|
||||
When closing a Pull Request, it needs to be acknowledging the time, effort, and interest demonstrated by the person which submitted it. As mentioned previously, it is not the intent of the team to dismiss a stalled pull request entirely but to merely to clear up our queue, so a message like the one below is warranted when closing a pull request that went stale:
|
||||
|
||||
Hi <contributor>,
|
||||
|
||||
First of all we would like to thank you for your time and effort on working on this, the pytest team deeply appreciates it.
|
||||
First of all, we would like to thank you for your time and effort on working on this, the pytest team deeply appreciates it.
|
||||
|
||||
We noticed it has been awhile since you have updated this PR, however. pytest is a high activity project, with many issues/PRs being opened daily, so it is hard for us maintainers to track which PRs are ready for merging, for review, or need more attention.
|
||||
|
||||
So for those reasons we think it is best to close the PR for now, but with the only intention to cleanup our queue, it is by no means a rejection of your changes. We still encourage you to re-open this PR (it is just a click of a button away) when you are ready to get back to it.
|
||||
So for those reasons we, think it is best to close the PR for now, but with the only intention to clean up our queue, it is by no means a rejection of your changes. We still encourage you to re-open this PR (it is just a click of a button away) when you are ready to get back to it.
|
||||
|
||||
Again we appreciate your time for working on this, and hope you might get back to this at a later time!
|
||||
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2004-2020 Holger Krekel and others
|
||||
Copyright (c) 2004-2021 Holger Krekel and others
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
|
||||
18
README.rst
18
README.rst
@@ -1,6 +1,7 @@
|
||||
.. image:: https://docs.pytest.org/en/stable/_static/pytest1.png
|
||||
.. image:: https://github.com/pytest-dev/pytest/raw/main/doc/en/img/pytest_logo_curves.svg
|
||||
:target: https://docs.pytest.org/en/stable/
|
||||
:align: center
|
||||
:height: 200
|
||||
:alt: pytest
|
||||
|
||||
|
||||
@@ -15,16 +16,17 @@
|
||||
.. image:: https://img.shields.io/pypi/pyversions/pytest.svg
|
||||
:target: https://pypi.org/project/pytest/
|
||||
|
||||
.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/master/graph/badge.svg
|
||||
.. image:: https://codecov.io/gh/pytest-dev/pytest/branch/main/graph/badge.svg
|
||||
:target: https://codecov.io/gh/pytest-dev/pytest
|
||||
:alt: Code coverage Status
|
||||
|
||||
.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
|
||||
:target: https://travis-ci.org/pytest-dev/pytest
|
||||
|
||||
.. image:: https://github.com/pytest-dev/pytest/workflows/main/badge.svg
|
||||
:target: https://github.com/pytest-dev/pytest/actions?query=workflow%3Amain
|
||||
|
||||
.. image:: https://results.pre-commit.ci/badge/github/pytest-dev/pytest/main.svg
|
||||
:target: https://results.pre-commit.ci/latest/github/pytest-dev/pytest/main
|
||||
:alt: pre-commit.ci status
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/psf/black
|
||||
|
||||
@@ -91,7 +93,7 @@ Features
|
||||
|
||||
- Python 3.6+ and PyPy3
|
||||
|
||||
- Rich plugin architecture, with over 850+ `external plugins <http://plugincompat.herokuapp.com>`_ and thriving community
|
||||
- Rich plugin architecture, with over 850+ `external plugins <https://docs.pytest.org/en/latest/reference/plugin_list.html>`_ and thriving community
|
||||
|
||||
|
||||
Documentation
|
||||
@@ -149,8 +151,8 @@ Tidelift will coordinate the fix and disclosure.
|
||||
License
|
||||
-------
|
||||
|
||||
Copyright Holger Krekel and others, 2004-2020.
|
||||
Copyright Holger Krekel and others, 2004-2021.
|
||||
|
||||
Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
|
||||
|
||||
.. _`MIT`: https://github.com/pytest-dev/pytest/blob/master/LICENSE
|
||||
.. _`MIT`: https://github.com/pytest-dev/pytest/blob/main/LICENSE
|
||||
|
||||
112
RELEASING.rst
112
RELEASING.rst
@@ -14,59 +14,89 @@ Preparing: Automatic Method
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
We have developed an automated workflow for releases, that uses GitHub workflows and is triggered
|
||||
by opening an issue.
|
||||
by `manually running <https://docs.github.com/en/actions/managing-workflow-runs/manually-running-a-workflow>`__
|
||||
the `prepare-release-pr workflow <https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml>`__
|
||||
on GitHub Actions.
|
||||
|
||||
Bug-fix releases
|
||||
^^^^^^^^^^^^^^^^
|
||||
The automation will decide the new version number based on the following criteria:
|
||||
|
||||
A bug-fix release is always done from a maintenance branch, so for example to release bug-fix
|
||||
``5.1.2``, open a new issue and add this comment to the body::
|
||||
- If the "major release" input is set to "yes", release a new major release
|
||||
(e.g. 7.0.0 -> 8.0.0)
|
||||
- If there are any ``.feature.rst`` or ``.breaking.rst`` files in the
|
||||
``changelog`` directory, release a new minor release (e.g. 7.0.0 -> 7.1.0)
|
||||
- Otherwise, release a bugfix release (e.g. 7.0.0 -> 7.0.1)
|
||||
- If the "prerelease" input is set, append the string to the version number
|
||||
(e.g. 7.0.0 -> 8.0.0rc1), if "major" is set, and "prerelease" is set to `rc1`)
|
||||
|
||||
@pytestbot please prepare release from 5.1.x
|
||||
Bug-fix and minor releases
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Where ``5.1.x`` is the maintenance branch for the ``5.1`` series.
|
||||
Bug-fix and minor releases are always done from a maintenance branch. First,
|
||||
consider double-checking the ``changelog`` directory to see if there are any
|
||||
breaking changes or new features.
|
||||
|
||||
The automated workflow will publish a PR for a branch ``release-5.1.2``
|
||||
and notify it as a comment in the issue.
|
||||
For a new minor release, first create a new maintenance branch from ``main``::
|
||||
|
||||
Minor releases
|
||||
git fetch --all
|
||||
git branch 7.1.x upstream/main
|
||||
git push upstream 7.1.x
|
||||
|
||||
Then, trigger the workflow with the following inputs:
|
||||
|
||||
- branch: **7.1.x**
|
||||
- major release: **no**
|
||||
- prerelease: empty
|
||||
|
||||
Or via the commandline using `GitHub's cli <https://github.com/cli/cli>`__::
|
||||
|
||||
gh workflow run prepare-release-pr.yml -f branch=7.1.x -f major=no -f prerelease=
|
||||
|
||||
Where ``7.1.x`` is the maintenance branch for the ``7.1`` series. The automated
|
||||
workflow will publish a PR for a branch ``release-7.1.0``.
|
||||
|
||||
Similarly, for a bug-fix release, use the existing maintenance branch and
|
||||
trigger the workflow with e.g. ``branch: 7.0.x`` to get a new ``release-7.0.1``
|
||||
PR.
|
||||
|
||||
Major releases
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
1. Create a new maintenance branch from ``master``::
|
||||
1. Create a new maintenance branch from ``main``::
|
||||
|
||||
git fetch --all
|
||||
git branch 5.2.x upstream/master
|
||||
git push upstream 5.2.x
|
||||
git branch 8.0.x upstream/main
|
||||
git push upstream 8.0.x
|
||||
|
||||
2. Open a new issue and add this comment to the body::
|
||||
2. Trigger the workflow with the following inputs:
|
||||
|
||||
@pytestbot please prepare release from 5.2.x
|
||||
- branch: **8.0.x**
|
||||
- major release: **yes**
|
||||
- prerelease: empty
|
||||
|
||||
The automated workflow will publish a PR for a branch ``release-5.2.0`` and
|
||||
notify it as a comment in the issue.
|
||||
Or via the commandline::
|
||||
|
||||
Major and release candidates
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
gh workflow run prepare-release-pr.yml -f branch=8.0.x -f major=yes -f prerelease=
|
||||
|
||||
1. Create a new maintenance branch from ``master``::
|
||||
|
||||
git fetch --all
|
||||
git branch 6.0.x upstream/master
|
||||
git push upstream 6.0.x
|
||||
|
||||
2. For a **major release**, open a new issue and add this comment in the body::
|
||||
|
||||
@pytestbot please prepare major release from 6.0.x
|
||||
|
||||
For a **release candidate**, the comment must be (TODO: `#7551 <https://github.com/pytest-dev/pytest/issues/7551>`__)::
|
||||
|
||||
@pytestbot please prepare release candidate from 6.0.x
|
||||
|
||||
The automated workflow will publish a PR for a branch ``release-6.0.0`` and
|
||||
notify it as a comment in the issue.
|
||||
The automated workflow will publish a PR for a branch ``release-8.0.0``.
|
||||
|
||||
At this point on, this follows the same workflow as other maintenance branches: bug-fixes are merged
|
||||
into ``master`` and ported back to the maintenance branch, even for release candidates.
|
||||
into ``main`` and ported back to the maintenance branch, even for release candidates.
|
||||
|
||||
Release candidates
|
||||
^^^^^^^^^^^^^^^^^^
|
||||
|
||||
To release a release candidate, set the "prerelease" input to the version number
|
||||
suffix to use. To release a ``8.0.0rc1``, proceed like under "major releases", but set:
|
||||
|
||||
- branch: 8.0.x
|
||||
- major release: yes
|
||||
- prerelease: **rc1**
|
||||
|
||||
Or via the commandline::
|
||||
|
||||
gh workflow run prepare-release-pr.yml -f branch=8.0.x -f major=yes -f prerelease=rc1
|
||||
|
||||
The automated workflow will publish a PR for a branch ``release-8.0.0rc1``.
|
||||
|
||||
**A note about release candidates**
|
||||
|
||||
@@ -83,7 +113,7 @@ to be executed on that platform.
|
||||
To release a version ``MAJOR.MINOR.PATCH``, follow these steps:
|
||||
|
||||
#. For major and minor releases, create a new branch ``MAJOR.MINOR.x`` from
|
||||
``upstream/master`` and push it to ``upstream``.
|
||||
``upstream/main`` and push it to ``upstream``.
|
||||
|
||||
#. Create a branch ``release-MAJOR.MINOR.PATCH`` from the ``MAJOR.MINOR.x`` branch.
|
||||
|
||||
@@ -114,18 +144,18 @@ Both automatic and manual processes described above follow the same steps from t
|
||||
|
||||
#. Merge the PR.
|
||||
|
||||
#. Cherry-pick the CHANGELOG / announce files to the ``master`` branch::
|
||||
#. Cherry-pick the CHANGELOG / announce files to the ``main`` branch::
|
||||
|
||||
git fetch --all --prune
|
||||
git checkout origin/master -b cherry-pick-release
|
||||
git checkout upstream/main -b cherry-pick-release
|
||||
git cherry-pick -x -m1 upstream/MAJOR.MINOR.x
|
||||
|
||||
#. Open a PR for ``cherry-pick-release`` and merge it once CI passes. No need to wait for approvals if there were no conflicts on the previous step.
|
||||
|
||||
#. For major and minor releases, tag the release cherry-pick merge commit in master with
|
||||
#. For major and minor releases, tag the release cherry-pick merge commit in main with
|
||||
a dev tag for the next feature release::
|
||||
|
||||
git checkout master
|
||||
git checkout main
|
||||
git pull
|
||||
git tag MAJOR.{MINOR+1}.0.dev0
|
||||
git push git@github.com:pytest-dev/pytest.git MAJOR.{MINOR+1}.0.dev0
|
||||
|
||||
@@ -25,6 +25,7 @@ The current list of contributors receiving funding are:
|
||||
|
||||
* `@asottile`_
|
||||
* `@nicoddemus`_
|
||||
* `@The-Compiler`_
|
||||
|
||||
Contributors interested in receiving a part of the funds just need to submit a PR adding their
|
||||
name to the list. Contributors that want to stop receiving the funds should also submit a PR
|
||||
@@ -56,3 +57,4 @@ funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the
|
||||
|
||||
.. _`@asottile`: https://github.com/asottile
|
||||
.. _`@nicoddemus`: https://github.com/nicoddemus
|
||||
.. _`@The-Compiler`: https://github.com/The-Compiler
|
||||
|
||||
1
changelog/5105.doc.rst
Normal file
1
changelog/5105.doc.rst
Normal file
@@ -0,0 +1 @@
|
||||
Add automatically generated :ref:`plugin-list`. The list is updated on a periodic schedule.
|
||||
7
changelog/7259.feature.rst
Normal file
7
changelog/7259.feature.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
Added :meth:`cache.mkdir() <pytest.Cache.mkdir>`, which is similar to the existing :meth:`cache.makedir() <pytest.Cache.makedir>`,
|
||||
but returns a :class:`pathlib.Path` instead of a legacy ``py.path.local``.
|
||||
|
||||
Added a ``paths`` type to :meth:`parser.addini() <pytest.Parser.addini>`,
|
||||
as in ``parser.addini("mypaths", "my paths", type="paths")``,
|
||||
which is similar to the existing ``pathlist``,
|
||||
but returns a list of :class:`pathlib.Path` instead of legacy ``py.path.local``.
|
||||
12
changelog/7469.deprecation.rst
Normal file
12
changelog/7469.deprecation.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
Directly constructing the following classes is now deprecated:
|
||||
|
||||
- ``_pytest.mark.structures.Mark``
|
||||
- ``_pytest.mark.structures.MarkDecorator``
|
||||
- ``_pytest.mark.structures.MarkGenerator``
|
||||
- ``_pytest.python.Metafunc``
|
||||
- ``_pytest.runner.CallInfo``
|
||||
- ``_pytest._code.ExceptionInfo``
|
||||
- ``_pytest.config.argparsing.Parser``
|
||||
- ``_pytest.config.argparsing.OptionGroup``
|
||||
|
||||
These have always been considered private, but now issue a deprecation warning, which may become a hard error in pytest 7.0.0.
|
||||
19
changelog/7469.feature.rst
Normal file
19
changelog/7469.feature.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
The types of objects used in pytest's API are now exported so they may be used in type annotations.
|
||||
|
||||
The newly-exported types are:
|
||||
|
||||
- ``pytest.Config`` for :class:`Config <pytest.Config>`.
|
||||
- ``pytest.Mark`` for :class:`marks <pytest.Mark>`.
|
||||
- ``pytest.MarkDecorator`` for :class:`mark decorators <pytest.MarkDecorator>`.
|
||||
- ``pytest.MarkGenerator`` for the :class:`pytest.mark <pytest.MarkGenerator>` singleton.
|
||||
- ``pytest.Metafunc`` for the :class:`metafunc <pytest.MarkGenerator>` argument to the :func:`pytest_generate_tests <pytest.hookspec.pytest_generate_tests>` hook.
|
||||
- ``pytest.CallInfo`` for the :class:`CallInfo <pytest.CallInfo>` type passed to various hooks.
|
||||
- ``pytest.PytestPluginManager`` for :class:`PytestPluginManager <pytest.PytestPluginManager>`.
|
||||
- ``pytest.ExceptionInfo`` for the :class:`ExceptionInfo <pytest.ExceptionInfo>` type returned from :func:`pytest.raises` and passed to various hooks.
|
||||
- ``pytest.Parser`` for the :class:`Parser <pytest.Parser>` type passed to the :func:`pytest_addoption <pytest.hookspec.pytest_addoption>` hook.
|
||||
- ``pytest.OptionGroup`` for the :class:`OptionGroup <pytest.OptionGroup>` type returned from the :func:`parser.addgroup <pytest.Parser.getgroup>` method.
|
||||
|
||||
Constructing them directly is not supported; they are only meant for use in type annotations.
|
||||
Doing so will emit a deprecation warning, and may become a hard-error in pytest 7.0.
|
||||
|
||||
Subclassing them is also not supported. This is not currently enforced at runtime, but is detected by type-checkers such as mypy.
|
||||
2
changelog/7856.feature.rst
Normal file
2
changelog/7856.feature.rst
Normal file
@@ -0,0 +1,2 @@
|
||||
:ref:`--import-mode=importlib <import-modes>` now works with features that
|
||||
depend on modules being on :py:data:`sys.modules`, such as :mod:`pickle` and :mod:`dataclasses`.
|
||||
1
changelog/8061.bugfix.rst
Normal file
1
changelog/8061.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
Fixed failing staticmethod test cases if they are inherited from a parent test class.
|
||||
7
changelog/8144.feature.rst
Normal file
7
changelog/8144.feature.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
The following hooks now receive an additional ``pathlib.Path`` argument, equivalent to an existing ``py.path.local`` argument:
|
||||
|
||||
- :func:`pytest_ignore_collect <_pytest.hookspec.pytest_ignore_collect>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_collect_file <_pytest.hookspec.pytest_collect_file>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_pycollect_makemodule <_pytest.hookspec.pytest_pycollect_makemodule>` - The ``fspath`` parameter (equivalent to existing ``path`` parameter).
|
||||
- :func:`pytest_report_header <_pytest.hookspec.pytest_report_header>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
||||
- :func:`pytest_report_collectionfinish <_pytest.hookspec.pytest_report_collectionfinish>` - The ``startpath`` parameter (equivalent to existing ``startdir`` parameter).
|
||||
6
changelog/8174.trivial.rst
Normal file
6
changelog/8174.trivial.rst
Normal file
@@ -0,0 +1,6 @@
|
||||
The following changes have been made to internal pytest types/functions:
|
||||
|
||||
- The ``path`` property of ``_pytest.code.Code`` returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``path`` property of ``_pytest.code.TracebackEntry`` returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``_pytest.code.getfslineno()`` function returns ``Path`` instead of ``py.path.local``.
|
||||
- The ``_pytest.python.path_matches_patterns()`` function takes ``Path`` instead of ``py.path.local``.
|
||||
3
changelog/8192.bugfix.rst
Normal file
3
changelog/8192.bugfix.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
``testdir.makefile`` now silently accepts values which don't start with ``.`` to maintain backward compatibility with older pytest versions.
|
||||
|
||||
``pytester.makefile`` now issues a clearer error if the ``.`` is missing in the ``ext`` argument.
|
||||
7
changelog/8242.deprecation.rst
Normal file
7
changelog/8242.deprecation.rst
Normal file
@@ -0,0 +1,7 @@
|
||||
Raising :class:`unittest.SkipTest` to skip collection of tests during the
|
||||
pytest collection phase is deprecated. Use :func:`pytest.skip` instead.
|
||||
|
||||
Note: This deprecation only relates to using `unittest.SkipTest` during test
|
||||
collection. You are probably not doing that. Ordinary usage of
|
||||
:class:`unittest.SkipTest` / :meth:`unittest.TestCase.skipTest` /
|
||||
:func:`unittest.skip` in unittest test cases is fully supported.
|
||||
1
changelog/8246.breaking.rst
Normal file
1
changelog/8246.breaking.rst
Normal file
@@ -0,0 +1 @@
|
||||
``--version`` now writes version information to ``stdout`` rather than ``stderr``.
|
||||
1
changelog/8248.trivial.rst
Normal file
1
changelog/8248.trivial.rst
Normal file
@@ -0,0 +1 @@
|
||||
Internal Restructure: let python.PyObjMixing inherit from nodes.Node to carry over typing information.
|
||||
1
changelog/8251.deprecation.rst
Normal file
1
changelog/8251.deprecation.rst
Normal file
@@ -0,0 +1 @@
|
||||
Deprecate ``Node.fspath`` as we plan to move off `py.path.local <https://py.readthedocs.io/en/latest/path.html>`__ and switch to :mod:``pathlib``.
|
||||
1
changelog/8251.feature.rst
Normal file
1
changelog/8251.feature.rst
Normal file
@@ -0,0 +1 @@
|
||||
Implement ``Node.path`` as a ``pathlib.Path``.
|
||||
3
changelog/8258.bugfix.rst
Normal file
3
changelog/8258.bugfix.rst
Normal file
@@ -0,0 +1,3 @@
|
||||
Fixed issue where pytest's ``faulthandler`` support would not dump traceback on crashes
|
||||
if the :mod:`faulthandler` module was already enabled during pytest startup (using
|
||||
``python -X dev -m pytest`` for example).
|
||||
5
changelog/8315.deprecation.rst
Normal file
5
changelog/8315.deprecation.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
|
||||
|
||||
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
||||
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
||||
1
changelog/8317.bugfix.rst
Normal file
1
changelog/8317.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
Fixed an issue where illegal directory characters derived from ``getpass.getuser()`` raised an ``OSError``.
|
||||
10
changelog/8335.improvement.rst
Normal file
10
changelog/8335.improvement.rst
Normal file
@@ -0,0 +1,10 @@
|
||||
Improved :func:`pytest.approx` assertion messages for sequences of numbers.
|
||||
|
||||
The assertion messages now dumps a table with the index and the error of each diff.
|
||||
Example::
|
||||
|
||||
> assert [1, 2, 3, 4] == pytest.approx([1, 3, 3, 5])
|
||||
E assert comparison failed for 2 values:
|
||||
E Index | Obtained | Expected
|
||||
E 1 | 2 | 3 +- 3.0e-06
|
||||
E 3 | 4 | 5 +- 5.0e-06
|
||||
1
changelog/8337.doc.rst
Normal file
1
changelog/8337.doc.rst
Normal file
@@ -0,0 +1 @@
|
||||
Recommend `numpy.testing <https://numpy.org/doc/stable/reference/routines.testing.html>`__ module on :func:`pytest.approx` documentation.
|
||||
1
changelog/8367.bugfix.rst
Normal file
1
changelog/8367.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
Fix ``Class.from_parent`` so it forwards extra keyword arguments to the constructor.
|
||||
1
changelog/8384.bugfix.rst
Normal file
1
changelog/8384.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
The ``@pytest.mark.skip`` decorator now correctly handles its arguments. When the ``reason`` argument is accidentally given both positional and as a keyword (e.g. because it was confused with ``skipif``), a ``TypeError`` now occurs. Before, such tests were silently skipped, and the positional argument ignored. Additionally, ``reason`` is now documented correctly as positional or keyword (rather than keyword-only).
|
||||
1
changelog/8394.bugfix.rst
Normal file
1
changelog/8394.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
Use private names for internal fixtures that handle classic setup/teardown so that they don't show up with the default ``--fixtures`` invocation (but they still show up with ``--fixtures -v``).
|
||||
5
changelog/8403.improvement.rst
Normal file
5
changelog/8403.improvement.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
By default, pytest will truncate long strings in assert errors so they don't clutter the output too much,
|
||||
currently at ``240`` characters by default.
|
||||
|
||||
However, in some cases the longer output helps, or is even crucial, to diagnose a failure. Using ``-v`` will
|
||||
now increase the truncation threshold to ``2400`` characters, and ``-vv`` or higher will disable truncation entirely.
|
||||
1
changelog/8411.trivial.rst
Normal file
1
changelog/8411.trivial.rst
Normal file
@@ -0,0 +1 @@
|
||||
Assert the outcomes for the issue 518 test and fix the test.
|
||||
1
changelog/8421.feature.rst
Normal file
1
changelog/8421.feature.rst
Normal file
@@ -0,0 +1 @@
|
||||
:func:`pytest.approx` now works on :class:`~decimal.Decimal` within mappings/dicts and sequences/lists.
|
||||
4
changelog/8447.deprecation.rst
Normal file
4
changelog/8447.deprecation.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
Defining a custom pytest node type which is both an item and a collector now issues a warning.
|
||||
It was never sanely supported and triggers hard to debug errors.
|
||||
|
||||
Instead, a separate collector node should be used, which collects the item. See :ref:`non-python tests` for an example.
|
||||
1
changelog/8456.bugfix.rst
Normal file
1
changelog/8456.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
The :confval:`required_plugins` config option now works correctly when pre-releases of plugins are installed, rather than falsely claiming that those plugins aren't installed at all.
|
||||
1
changelog/8464.bugfix.rst
Normal file
1
changelog/8464.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
``-c <config file>`` now also properly defines ``rootdir`` as the directory that contains ``<config file>``.
|
||||
1
changelog/8494.feature.rst
Normal file
1
changelog/8494.feature.rst
Normal file
@@ -0,0 +1 @@
|
||||
Python 3.10 is now supported.
|
||||
4
changelog/8503.trivial.rst
Normal file
4
changelog/8503.trivial.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
:meth:`pytest.MonkeyPatch.syspath_prepend` no longer fails when
|
||||
``setuptools`` is not installed.
|
||||
It now only calls :func:`pkg_resources.fixup_namespace_packages` if
|
||||
``pkg_resources`` was previously imported, because it is not needed otherwise.
|
||||
5
changelog/8509.improvement.rst
Normal file
5
changelog/8509.improvement.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
Fixed issue where `TestCase.setUpClass` is not called when a test has `/` in its name since pytest 6.2.0.
|
||||
|
||||
This refers to the path part in pytest node IDs, e.g. `TestClass::test_it` in the node ID `tests/test_file.py::TestClass::test_it`.
|
||||
|
||||
Now, instead of assuming that the test name does not contain ``/``, it is assumed that test path does not contain ``::``. We plan to hopefully make both of these work in the future.
|
||||
1
changelog/8548.bugfix.rst
Normal file
1
changelog/8548.bugfix.rst
Normal file
@@ -0,0 +1 @@
|
||||
Introduce fix to handle precision width in ``log-cli-format`` in turn to fix output coloring for certain formats.
|
||||
5
changelog/8606.feature.rst
Normal file
5
changelog/8606.feature.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
pytest invocations with ``--fixtures-per-test`` and ``--fixtures`` have been enabled with:
|
||||
|
||||
- Fixture location path printed with the fixture name.
|
||||
- First section of the fixture's docstring printed under the fixture name.
|
||||
- Whole of fixture's docstring printed under the fixture name using ``--verbose`` option.
|
||||
4
changelog/8645.improvement.rst
Normal file
4
changelog/8645.improvement.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
Reducing confusion from `pytest.warns(None)` by:
|
||||
|
||||
- Allowing no arguments to be passed in order to catch any exception (no argument defaults to `Warning`).
|
||||
- Emit a deprecation warning if passed `None`.
|
||||
1
changelog/8655.doc.rst
Normal file
1
changelog/8655.doc.rst
Normal file
@@ -0,0 +1 @@
|
||||
Help text for ``--pdbcls`` more accurately reflects the option's behavior.
|
||||
1
changelog/8761.feature.rst
Normal file
1
changelog/8761.feature.rst
Normal file
@@ -0,0 +1 @@
|
||||
New :ref:`version-tuple` attribute, which makes it simpler for users to do something depending on the pytest version (such as declaring hooks which are introduced in later versions).
|
||||
@@ -1,12 +1,19 @@
|
||||
<h3><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
|
||||
<h3>Contents</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="{{ pathto('index') }}">Home</a></li>
|
||||
<li><a href="{{ pathto('getting-started') }}">Install</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Contents</a></li>
|
||||
<li><a href="{{ pathto('reference') }}">API Reference</a></li>
|
||||
<li><a href="{{ pathto('example/index') }}">Examples</a></li>
|
||||
<li><a href="{{ pathto('customize') }}">Customize</a></li>
|
||||
|
||||
<li><a href="{{ pathto('getting-started') }}">Get started</a></li>
|
||||
<li><a href="{{ pathto('how-to/index') }}">How-to guides</a></li>
|
||||
<li><a href="{{ pathto('reference/index') }}">Reference guides</a></li>
|
||||
<li><a href="{{ pathto('explanation/index') }}">Explanation</a></li>
|
||||
<li><a href="{{ pathto('contents') }}">Complete table of contents</a></li>
|
||||
<li><a href="{{ pathto('example/index') }}">Library of examples</a></li>
|
||||
</ul>
|
||||
|
||||
<h3>About the project</h3>
|
||||
|
||||
<ul>
|
||||
<li><a href="{{ pathto('changelog') }}">Changelog</a></li>
|
||||
<li><a href="{{ pathto('contributing') }}">Contributing</a></li>
|
||||
<li><a href="{{ pathto('backwards-compatibility') }}">Backwards Compatibility</a></li>
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
<ul>
|
||||
<li><a href="https://pypi.org/project/pytest/">pytest @ PyPI</a></li>
|
||||
<li><a href="https://github.com/pytest-dev/pytest/">pytest @ GitHub</a></li>
|
||||
<li><a href="http://plugincompat.herokuapp.com/">3rd party plugins</a></li>
|
||||
<li><a href="https://github.com/pytest-dev/pytest/issues">Issue Tracker</a></li>
|
||||
<li><a href="https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf">PDF Documentation</a>
|
||||
</ul>
|
||||
|
||||
@@ -6,6 +6,8 @@ Release announcements
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
release-6.2.4
|
||||
release-6.2.3
|
||||
release-6.2.2
|
||||
release-6.2.1
|
||||
release-6.2.0
|
||||
|
||||
@@ -24,7 +24,7 @@ If you want to install or upgrade pytest, just type one of::
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
holger krekel / https://merlinux.eu/
|
||||
|
||||
Changes between 2.0.3 and 2.1.0
|
||||
----------------------------------------------
|
||||
|
||||
@@ -20,7 +20,7 @@ If you want to install or upgrade pytest, just type one of::
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
holger krekel / https://merlinux.eu/
|
||||
|
||||
Changes between 2.1.0 and 2.1.1
|
||||
----------------------------------------------
|
||||
|
||||
@@ -19,7 +19,7 @@ If you want to install or upgrade pytest, just type one of::
|
||||
easy_install -U pytest
|
||||
|
||||
best,
|
||||
holger krekel / http://merlinux.eu
|
||||
holger krekel / https://merlinux.eu/
|
||||
|
||||
Changes between 2.1.1 and 2.1.2
|
||||
----------------------------------------
|
||||
|
||||
19
doc/en/announce/release-6.2.3.rst
Normal file
19
doc/en/announce/release-6.2.3.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
pytest-6.2.3
|
||||
=======================================
|
||||
|
||||
pytest 6.2.3 has just been released to PyPI.
|
||||
|
||||
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
|
||||
|
||||
Thanks to all of the contributors to this release:
|
||||
|
||||
* Bruno Oliveira
|
||||
* Ran Benita
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
22
doc/en/announce/release-6.2.4.rst
Normal file
22
doc/en/announce/release-6.2.4.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
pytest-6.2.4
|
||||
=======================================
|
||||
|
||||
pytest 6.2.4 has just been released to PyPI.
|
||||
|
||||
This is a bug-fix release, being a drop-in replacement. To upgrade::
|
||||
|
||||
pip install --upgrade pytest
|
||||
|
||||
The full changelog is available at https://docs.pytest.org/en/stable/changelog.html.
|
||||
|
||||
Thanks to all of the contributors to this release:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Christian Maurer
|
||||
* Florian Bruhin
|
||||
* Ran Benita
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
@@ -6,7 +6,7 @@ Pytest API and builtin fixtures
|
||||
================================================
|
||||
|
||||
|
||||
Most of the information of this page has been moved over to :ref:`reference`.
|
||||
Most of the information of this page has been moved over to :ref:`api-reference`.
|
||||
|
||||
For information on plugin hooks and objects, see :ref:`plugins`.
|
||||
|
||||
@@ -61,7 +61,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
namespace of doctests.
|
||||
|
||||
pytestconfig [session scope]
|
||||
Session-scoped fixture that returns the :class:`_pytest.config.Config` object.
|
||||
Session-scoped fixture that returns the :class:`pytest.Config` object.
|
||||
|
||||
Example::
|
||||
|
||||
@@ -144,14 +144,14 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
recwarn
|
||||
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
|
||||
|
||||
See http://docs.python.org/library/warnings.html for information
|
||||
See https://docs.python.org/library/warnings.html for information
|
||||
on warning categories.
|
||||
|
||||
tmpdir_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.
|
||||
Return a :class:`pytest.TempdirFactory` instance for the test session.
|
||||
|
||||
tmp_path_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
|
||||
Return a :class:`pytest.TempPathFactory` instance for the test session.
|
||||
|
||||
tmpdir
|
||||
Return a temporary directory path object which is unique to each test
|
||||
|
||||
@@ -28,6 +28,33 @@ with advance notice in the **Deprecations** section of releases.
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 6.2.4 (2021-05-04)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#8539 <https://github.com/pytest-dev/pytest/issues/8539>`_: Fixed assertion rewriting on Python 3.10.
|
||||
|
||||
|
||||
pytest 6.2.3 (2021-04-03)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#8414 <https://github.com/pytest-dev/pytest/issues/8414>`_: pytest used to create directories under ``/tmp`` with world-readable
|
||||
permissions. This means that any user in the system was able to read
|
||||
information written by tests in temporary directories (such as those created by
|
||||
the ``tmp_path``/``tmpdir`` fixture). Now the directories are created with
|
||||
private permissions.
|
||||
|
||||
pytest used to silenty use a pre-existing ``/tmp/pytest-of-<username>`` directory,
|
||||
even if owned by another user. This means another user could pre-create such a
|
||||
directory and gain control of another user's temporary directory. Now such a
|
||||
condition results in an error.
|
||||
|
||||
|
||||
pytest 6.2.2 (2021-01-25)
|
||||
=========================
|
||||
|
||||
@@ -1028,7 +1055,7 @@ Bug Fixes
|
||||
- `#7110 <https://github.com/pytest-dev/pytest/issues/7110>`_: Fixed regression: ``asyncbase.TestCase`` tests are executed correctly again.
|
||||
|
||||
|
||||
- `#7143 <https://github.com/pytest-dev/pytest/issues/7143>`_: Fix ``File.from_constructor`` so it forwards extra keyword arguments to the constructor.
|
||||
- `#7143 <https://github.com/pytest-dev/pytest/issues/7143>`_: Fix ``File.from_parent`` so it forwards extra keyword arguments to the constructor.
|
||||
|
||||
|
||||
- `#7145 <https://github.com/pytest-dev/pytest/issues/7145>`_: Classes with broken ``__getattribute__`` methods are displayed correctly during failures.
|
||||
@@ -3090,12 +3117,12 @@ Features
|
||||
will not issue the warning.
|
||||
|
||||
|
||||
- `#3632 <https://github.com/pytest-dev/pytest/issues/3632>`_: Richer equality comparison introspection on ``AssertionError`` for objects created using `attrs <http://www.attrs.org/en/stable/>`__ or `dataclasses <https://docs.python.org/3/library/dataclasses.html>`_ (Python 3.7+, `backported to 3.6 <https://pypi.org/project/dataclasses>`__).
|
||||
- `#3632 <https://github.com/pytest-dev/pytest/issues/3632>`_: Richer equality comparison introspection on ``AssertionError`` for objects created using `attrs <https://www.attrs.org/en/stable/>`__ or `dataclasses <https://docs.python.org/3/library/dataclasses.html>`_ (Python 3.7+, `backported to 3.6 <https://pypi.org/project/dataclasses>`__).
|
||||
|
||||
|
||||
- `#4278 <https://github.com/pytest-dev/pytest/issues/4278>`_: ``CACHEDIR.TAG`` files are now created inside cache directories.
|
||||
|
||||
Those files are part of the `Cache Directory Tagging Standard <http://www.bford.info/cachedir/spec.html>`__, and can
|
||||
Those files are part of the `Cache Directory Tagging Standard <https://bford.info/cachedir/spec.html>`__, and can
|
||||
be used by backup or synchronization programs to identify pytest's cache directory as such.
|
||||
|
||||
|
||||
@@ -5079,7 +5106,7 @@ Improved Documentation
|
||||
|
||||
- In one of the simple examples, use ``pytest_collection_modifyitems()`` to skip
|
||||
tests based on a command-line option, allowing its sharing while preventing a
|
||||
user error when acessing ``pytest.config`` before the argument parsing.
|
||||
user error when accessing ``pytest.config`` before the argument parsing.
|
||||
(`#2653 <https://github.com/pytest-dev/pytest/issues/2653>`_)
|
||||
|
||||
|
||||
@@ -5491,7 +5518,7 @@ Changes
|
||||
Thanks `@ojii`_ for the PR.
|
||||
|
||||
* Replace minor/patch level version numbers in the documentation with placeholders.
|
||||
This significantly reduces change-noise as different contributors regnerate
|
||||
This significantly reduces change-noise as different contributors regenerate
|
||||
the documentation on different platforms.
|
||||
Thanks `@RonnyPfannschmidt`_ for the PR.
|
||||
|
||||
@@ -8448,7 +8475,7 @@ Bug fixes:
|
||||
|
||||
- fixes for making the jython/win32 combination work, note however:
|
||||
jython2.5.1/win32 does not provide a command line launcher, see
|
||||
http://bugs.jython.org/issue1491 . See pylib install documentation
|
||||
https://bugs.jython.org/issue1491 . See pylib install documentation
|
||||
for how to work around.
|
||||
|
||||
- fixes for handling of unicode exception values and unprintable objects
|
||||
|
||||
@@ -35,6 +35,7 @@ release = ".".join(version.split(".")[:2])
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
autodoc_member_order = "bysource"
|
||||
autodoc_typehints = "description"
|
||||
todo_include_todos = 1
|
||||
|
||||
# -- General configuration -----------------------------------------------------
|
||||
@@ -70,7 +71,7 @@ master_doc = "contents"
|
||||
|
||||
# General information about the project.
|
||||
project = "pytest"
|
||||
copyright = "2015–2020, holger krekel and pytest-dev team"
|
||||
copyright = "2015–2021, holger krekel and pytest-dev team"
|
||||
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
@@ -159,7 +160,7 @@ html_short_title = "pytest-%s" % release
|
||||
|
||||
# The name of an image file (relative to this directory) to place at the top
|
||||
# of the sidebar.
|
||||
html_logo = "img/pytest1.png"
|
||||
html_logo = "img/pytest_logo_curves.svg"
|
||||
|
||||
# The name of an image file (within the static path) to use as favicon of the
|
||||
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
@@ -251,7 +252,7 @@ latex_documents = [
|
||||
"contents",
|
||||
"pytest.tex",
|
||||
"pytest Documentation",
|
||||
"holger krekel, trainer and consultant, http://merlinux.eu",
|
||||
"holger krekel, trainer and consultant, https://merlinux.eu/",
|
||||
"manual",
|
||||
)
|
||||
]
|
||||
@@ -292,7 +293,7 @@ man_pages = [("usage", "pytest", "pytest usage", ["holger krekel at merlinux eu"
|
||||
epub_title = "pytest"
|
||||
epub_author = "holger krekel at merlinux eu"
|
||||
epub_publisher = "holger krekel at merlinux eu"
|
||||
epub_copyright = "2013-2020, holger krekel et alii"
|
||||
epub_copyright = "2013-2021, holger krekel et alii"
|
||||
|
||||
# The language of the text. It defaults to the language option
|
||||
# or en if the language is not set.
|
||||
|
||||
@@ -16,12 +16,13 @@ Contact channels
|
||||
|
||||
- `pytest-dev at python.org (mailing list)`_ pytest specific announcements and discussions.
|
||||
|
||||
- `pytest-commit at python.org (mailing list)`_: for commits and new issues
|
||||
|
||||
- :doc:`contribution guide <contributing>` for help on submitting pull
|
||||
requests to GitHub.
|
||||
|
||||
- ``#pylib`` on irc.freenode.net IRC channel for random questions.
|
||||
- ``#pytest`` `on irc.libera.chat <ircs://irc.libera.chat:6697/#pytest>`_ IRC
|
||||
channel for random questions (using an IRC client, `via webchat
|
||||
<https://web.libera.chat/#pytest>`_, or `via Matrix
|
||||
<https://matrix.to/#/%23pytest:libera.chat>`_).
|
||||
|
||||
- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
|
||||
|
||||
@@ -30,19 +31,19 @@ Contact channels
|
||||
consulting.
|
||||
|
||||
.. _`pytest issue tracker`: https://github.com/pytest-dev/pytest/issues
|
||||
.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||
.. _`old issue tracker`: https://bitbucket.org/hpk42/py-trunk/issues/
|
||||
|
||||
.. _`merlinux.eu`: http://merlinux.eu
|
||||
.. _`merlinux.eu`: https://merlinux.eu/
|
||||
|
||||
.. _`get an account`:
|
||||
|
||||
.. _tetamap: http://tetamap.wordpress.com
|
||||
.. _tetamap: https://tetamap.wordpress.com/
|
||||
|
||||
.. _`@pylibcommit`: http://twitter.com/pylibcommit
|
||||
.. _`@pylibcommit`: https://twitter.com/pylibcommit
|
||||
|
||||
|
||||
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
|
||||
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
||||
.. _FOAF: https://en.wikipedia.org/wiki/FOAF
|
||||
.. _`py-dev`:
|
||||
.. _`development mailing list`:
|
||||
.. _`pytest-dev at python.org (mailing list)`: http://mail.python.org/mailman/listinfo/pytest-dev
|
||||
|
||||
@@ -7,37 +7,81 @@ Full pytest documentation
|
||||
|
||||
.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||
|
||||
|
||||
Start here
|
||||
-----------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
getting-started
|
||||
usage
|
||||
existingtestsuite
|
||||
assert
|
||||
fixture
|
||||
mark
|
||||
monkeypatch
|
||||
tmpdir
|
||||
capture
|
||||
warnings
|
||||
doctest
|
||||
skipping
|
||||
parametrize
|
||||
cache
|
||||
unittest
|
||||
nose
|
||||
xunit_setup
|
||||
plugins
|
||||
writing_plugins
|
||||
logging
|
||||
reference
|
||||
|
||||
goodpractices
|
||||
flaky
|
||||
pythonpath
|
||||
customize
|
||||
|
||||
How-to guides
|
||||
-------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
how-to/usage
|
||||
how-to/assert
|
||||
how-to/fixtures
|
||||
how-to/mark
|
||||
how-to/parametrize
|
||||
how-to/tmpdir
|
||||
how-to/monkeypatch
|
||||
how-to/doctest
|
||||
how-to/cache
|
||||
|
||||
how-to/logging
|
||||
how-to/capture-stdout-stderr
|
||||
how-to/capture-warnings
|
||||
how-to/skipping
|
||||
|
||||
how-to/plugins
|
||||
how-to/writing_plugins
|
||||
how-to/writing_hook_functions
|
||||
|
||||
how-to/existingtestsuite
|
||||
how-to/unittest
|
||||
how-to/nose
|
||||
how-to/xunit_setup
|
||||
|
||||
how-to/bash-completion
|
||||
|
||||
|
||||
Reference guides
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
reference/fixtures
|
||||
reference/plugin_list
|
||||
reference/customize
|
||||
reference/reference
|
||||
|
||||
|
||||
Explanation
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
explanation/anatomy
|
||||
explanation/fixtures
|
||||
explanation/goodpractices
|
||||
explanation/flaky
|
||||
explanation/pythonpath
|
||||
|
||||
|
||||
Further topics
|
||||
-----------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
example/index
|
||||
bash-completion
|
||||
|
||||
backwards-compatibility
|
||||
deprecations
|
||||
@@ -51,6 +95,7 @@ Full pytest documentation
|
||||
license
|
||||
contact
|
||||
|
||||
history
|
||||
historical-notes
|
||||
talks
|
||||
projects
|
||||
|
||||
@@ -18,6 +18,71 @@ Deprecated Features
|
||||
Below is a complete list of all pytest features which are considered deprecated. Using those features will issue
|
||||
:class:`PytestWarning` or subclasses, which can be filtered using :ref:`standard warning filters <warnings>`.
|
||||
|
||||
|
||||
``py.path.local`` arguments for hooks replaced with ``pathlib.Path``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
In order to support the transition to :mod:`pathlib`, the following hooks now receive additional arguments:
|
||||
|
||||
* :func:`pytest_ignore_collect(fspath: pathlib.Path) <_pytest.hookspec.pytest_ignore_collect>`
|
||||
* :func:`pytest_collect_file(fspath: pathlib.Path) <_pytest.hookspec.pytest_collect_file>`
|
||||
* :func:`pytest_pycollect_makemodule(fspath: pathlib.Path) <_pytest.hookspec.pytest_pycollect_makemodule>`
|
||||
* :func:`pytest_report_header(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_header>`
|
||||
* :func:`pytest_report_collectionfinish(startpath: pathlib.Path) <_pytest.hookspec.pytest_report_collectionfinish>`
|
||||
|
||||
The accompanying ``py.path.local`` based paths have been deprecated: plugins which manually invoke those hooks should only pass the new ``pathlib.Path`` arguments, and users should change their hook implementations to use the new ``pathlib.Path`` arguments.
|
||||
|
||||
|
||||
``Node.fspath`` in favor of ``pathlib`` and ``Node.path``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.3
|
||||
|
||||
As pytest tries to move off `py.path.local <https://py.readthedocs.io/en/latest/path.html>`__ we ported most of the node internals to :mod:`pathlib`.
|
||||
|
||||
Pytest will provide compatibility for quite a while.
|
||||
|
||||
Diamond inheritance between :class:`pytest.File` and :class:`pytest.Item`
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.3
|
||||
|
||||
Inheriting from both Item and file at once has never been supported officially,
|
||||
however some plugins providing linting/code analysis have been using this as a hack.
|
||||
|
||||
This practice is now officially deprecated and a common way to fix this is `example pr fixing inheritance`_.
|
||||
|
||||
|
||||
|
||||
.. _example pr fixing inheritance: https://github.com/asmeurer/pytest-flakes/pull/40/files
|
||||
|
||||
|
||||
Backward compatibilities in ``Parser.addoption``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 2.4
|
||||
|
||||
Several behaviors of :meth:`Parser.addoption <pytest.Parser.addoption>` are now
|
||||
scheduled for removal in pytest 7 (deprecated since pytest 2.4.0):
|
||||
|
||||
- ``parser.addoption(..., help=".. %default ..")`` - use ``%(default)s`` instead.
|
||||
- ``parser.addoption(..., type="int/string/float/complex")`` - use ``type=int`` etc. instead.
|
||||
|
||||
|
||||
Raising ``unittest.SkipTest`` during collection
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 6.3
|
||||
|
||||
Raising :class:`unittest.SkipTest` to skip collection of tests during the
|
||||
pytest collection phase is deprecated. Use :func:`pytest.skip` instead.
|
||||
|
||||
Note: This deprecation only relates to using `unittest.SkipTest` during test
|
||||
collection. You are probably not doing that. Ordinary usage of
|
||||
:class:`unittest.SkipTest` / :meth:`unittest.TestCase.skipTest` /
|
||||
:func:`unittest.skip` in unittest test cases is fully supported.
|
||||
|
||||
|
||||
The ``--strict`` command-line option
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -397,8 +462,8 @@ Metafunc.addcall
|
||||
|
||||
.. versionremoved:: 4.0
|
||||
|
||||
``_pytest.python.Metafunc.addcall`` was a precursor to the current parametrized mechanism. Users should use
|
||||
:meth:`_pytest.python.Metafunc.parametrize` instead.
|
||||
``Metafunc.addcall`` was a precursor to the current parametrized mechanism. Users should use
|
||||
:meth:`pytest.Metafunc.parametrize` instead.
|
||||
|
||||
Example:
|
||||
|
||||
|
||||
@@ -4,4 +4,4 @@ Development Guide
|
||||
|
||||
The contributing guidelines are to be found :ref:`here <contributing>`.
|
||||
The release procedure for pytest is documented on
|
||||
`GitHub <https://github.com/pytest-dev/pytest/blob/master/RELEASING.rst>`_.
|
||||
`GitHub <https://github.com/pytest-dev/pytest/blob/main/RELEASING.rst>`_.
|
||||
|
||||
@@ -5,9 +5,9 @@ failure_demo = os.path.join(os.path.dirname(__file__), "failure_demo.py")
|
||||
pytest_plugins = ("pytester",)
|
||||
|
||||
|
||||
def test_failure_demo_fails_properly(testdir):
|
||||
target = testdir.tmpdir.join(os.path.basename(failure_demo))
|
||||
def test_failure_demo_fails_properly(pytester):
|
||||
target = pytester.path.joinpath(os.path.basename(failure_demo))
|
||||
shutil.copy(failure_demo, target)
|
||||
result = testdir.runpytest(target, syspathinsert=True)
|
||||
result = pytester.runpytest(target, syspathinsert=True)
|
||||
result.stdout.fnmatch_lines(["*44 failed*"])
|
||||
assert result.ret != 0
|
||||
|
||||
@@ -13,12 +13,12 @@ answers.
|
||||
|
||||
For basic examples, see
|
||||
|
||||
- :doc:`../getting-started` for basic introductory examples
|
||||
- :ref:`get-started` for basic introductory examples
|
||||
- :ref:`assert` for basic assertion examples
|
||||
- :ref:`Fixtures <fixtures>` for basic fixture/setup examples
|
||||
- :ref:`parametrize` for basic test function parametrization
|
||||
- :doc:`../unittest` for basic unittest integration
|
||||
- :doc:`../nose` for basic nosetests integration
|
||||
- :ref:`unittest` for basic unittest integration
|
||||
- :ref:`noseintegration` for basic nosetests integration
|
||||
|
||||
The following examples aim at various use cases you might encounter.
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@ pythonlist = ["python3.5", "python3.6", "python3.7"]
|
||||
|
||||
|
||||
@pytest.fixture(params=pythonlist)
|
||||
def python1(request, tmpdir):
|
||||
picklefile = tmpdir.join("data.pickle")
|
||||
def python1(request, tmp_path):
|
||||
picklefile = tmp_path / "data.pickle"
|
||||
return Python(request.param, picklefile)
|
||||
|
||||
|
||||
@@ -30,8 +30,8 @@ class Python:
|
||||
self.picklefile = picklefile
|
||||
|
||||
def dumps(self, obj):
|
||||
dumpfile = self.picklefile.dirpath("dump.py")
|
||||
dumpfile.write(
|
||||
dumpfile = self.picklefile.with_name("dump.py")
|
||||
dumpfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
import pickle
|
||||
@@ -46,8 +46,8 @@ class Python:
|
||||
subprocess.check_call((self.pythonpath, str(dumpfile)))
|
||||
|
||||
def load_and_is_true(self, expression):
|
||||
loadfile = self.picklefile.dirpath("load.py")
|
||||
loadfile.write(
|
||||
loadfile = self.picklefile.with_name("load.py")
|
||||
loadfile.write_text(
|
||||
textwrap.dedent(
|
||||
r"""
|
||||
import pickle
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_collect_file(parent, path):
|
||||
if path.ext == ".yaml" and path.basename.startswith("test"):
|
||||
return YamlFile.from_parent(parent, fspath=path)
|
||||
def pytest_collect_file(parent, fspath):
|
||||
if fspath.suffix == ".yaml" and fspath.name.startswith("test"):
|
||||
return YamlFile.from_parent(parent, path=fspath)
|
||||
|
||||
|
||||
class YamlFile(pytest.File):
|
||||
@@ -12,7 +12,7 @@ class YamlFile(pytest.File):
|
||||
# We need a yaml parser, e.g. PyYAML.
|
||||
import yaml
|
||||
|
||||
raw = yaml.safe_load(self.fspath.open())
|
||||
raw = yaml.safe_load(self.path.open())
|
||||
for name, spec in sorted(raw.items()):
|
||||
yield YamlItem.from_parent(self, name=name, spec=spec)
|
||||
|
||||
|
||||
@@ -97,10 +97,10 @@ the argument name:
|
||||
|
||||
# content of test_time.py
|
||||
|
||||
import pytest
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import pytest
|
||||
|
||||
testdata = [
|
||||
(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
|
||||
(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
|
||||
@@ -508,11 +508,12 @@ Running it results in some skips if we don't have all the python interpreters in
|
||||
.. code-block:: pytest
|
||||
|
||||
. $ pytest -rs -q multipython.py
|
||||
ssssssssssss...ssssssssssss [100%]
|
||||
sssssssssssssssssssssssssss [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [12] multipython.py:29: 'python3.5' not found
|
||||
SKIPPED [12] multipython.py:29: 'python3.7' not found
|
||||
3 passed, 24 skipped in 0.12s
|
||||
SKIPPED [9] multipython.py:29: 'python3.5' not found
|
||||
SKIPPED [9] multipython.py:29: 'python3.6' not found
|
||||
SKIPPED [9] multipython.py:29: 'python3.7' not found
|
||||
27 skipped in 0.12s
|
||||
|
||||
Indirect parametrization of optional implementations/imports
|
||||
--------------------------------------------------------------------
|
||||
|
||||
@@ -69,7 +69,7 @@ Here is a basic pattern to achieve this:
|
||||
|
||||
|
||||
For this to work we need to add a command line option and
|
||||
provide the ``cmdopt`` through a :ref:`fixture function <fixture function>`:
|
||||
provide the ``cmdopt`` through a :ref:`fixture function <fixture>`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -139,10 +139,66 @@ And now with supplying a command line option:
|
||||
FAILED test_sample.py::test_answer - assert 0
|
||||
1 failed in 0.12s
|
||||
|
||||
You can see that the command line option arrived in our test. This
|
||||
completes the basic pattern. However, one often rather wants to process
|
||||
command line options outside of the test and rather pass in different or
|
||||
more complex objects.
|
||||
You can see that the command line option arrived in our test.
|
||||
|
||||
We could add simple validation for the input by listing the choices:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--cmdopt",
|
||||
action="store",
|
||||
default="type1",
|
||||
help="my option: type1 or type2",
|
||||
choices=("type1", "type2"),
|
||||
)
|
||||
|
||||
Now we'll get feedback on a bad argument:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -q --cmdopt=type3
|
||||
ERROR: usage: pytest [options] [file_or_dir] [file_or_dir] [...]
|
||||
pytest: error: argument --cmdopt: invalid choice: 'type3' (choose from 'type1', 'type2')
|
||||
|
||||
If you need to provide more detailed error messages, you can use the
|
||||
``type`` parameter and raise ``pytest.UsageError``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
import pytest
|
||||
|
||||
|
||||
def type_checker(value):
|
||||
msg = "cmdopt must specify a numeric type as typeNNN"
|
||||
if not value.startswith("type"):
|
||||
raise pytest.UsageError(msg)
|
||||
try:
|
||||
int(value[4:])
|
||||
except ValueError:
|
||||
raise pytest.UsageError(msg)
|
||||
|
||||
return value
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--cmdopt",
|
||||
action="store",
|
||||
default="type1",
|
||||
help="my option: type1 or type2",
|
||||
type=type_checker,
|
||||
)
|
||||
|
||||
This completes the basic pattern. However, one often rather wants to
|
||||
process command line options outside of the test and rather pass in
|
||||
different or more complex objects.
|
||||
|
||||
Dynamically adding command line options
|
||||
--------------------------------------------------------------
|
||||
@@ -621,7 +677,7 @@ Package/Directory-level fixtures (setups)
|
||||
-------------------------------------------------------
|
||||
|
||||
If you have nested test directories, you can have per-directory fixture scopes
|
||||
by placing fixture functions in a ``conftest.py`` file in that directory
|
||||
by placing fixture functions in a ``conftest.py`` file in that directory.
|
||||
You can use all types of fixtures including :ref:`autouse fixtures
|
||||
<autouse fixtures>` which are the equivalent of xUnit's setup/teardown
|
||||
concept. It's however recommended to have explicit fixture references in your
|
||||
@@ -768,8 +824,8 @@ case we just write some information out to a ``failures`` file:
|
||||
mode = "a" if os.path.exists("failures") else "w"
|
||||
with open("failures", mode) as f:
|
||||
# let's also access a fixture for the fun of it
|
||||
if "tmpdir" in item.fixturenames:
|
||||
extra = " ({})".format(item.funcargs["tmpdir"])
|
||||
if "tmp_path" in item.fixturenames:
|
||||
extra = " ({})".format(item.funcargs["tmp_path"])
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
@@ -781,7 +837,7 @@ if you then have failing tests:
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_module.py
|
||||
def test_fail1(tmpdir):
|
||||
def test_fail1(tmp_path):
|
||||
assert 0
|
||||
|
||||
|
||||
@@ -804,9 +860,9 @@ and run them:
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_fail1 ________________________________
|
||||
|
||||
tmpdir = local('PYTEST_TMPDIR/test_fail10')
|
||||
tmp_path = Path('PYTEST_TMPDIR/test_fail10')
|
||||
|
||||
def test_fail1(tmpdir):
|
||||
def test_fail1(tmp_path):
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
@@ -1012,7 +1068,7 @@ your frozen program work as the pytest runner by some clever
|
||||
argument handling during program startup. This allows you to
|
||||
have a single executable, which is usually more convenient.
|
||||
Please note that the mechanism for plugin discovery used by pytest
|
||||
(setupttools entry points) doesn't work with frozen executables so pytest
|
||||
(setuptools entry points) doesn't work with frozen executables so pytest
|
||||
can't find any third party plugins automatically. To include third party plugins
|
||||
like ``pytest-timeout`` they must be imported explicitly and passed on to pytest.main.
|
||||
|
||||
|
||||
46
doc/en/explanation/anatomy.rst
Normal file
46
doc/en/explanation/anatomy.rst
Normal file
@@ -0,0 +1,46 @@
|
||||
.. _test-anatomy:
|
||||
|
||||
Anatomy of a test
|
||||
=================
|
||||
|
||||
In the simplest terms, a test is meant to look at the result of a particular
|
||||
behavior, and make sure that result aligns with what you would expect.
|
||||
Behavior is not something that can be empirically measured, which is why writing
|
||||
tests can be challenging.
|
||||
|
||||
"Behavior" is the way in which some system **acts in response** to a particular
|
||||
situation and/or stimuli. But exactly *how* or *why* something is done is not
|
||||
quite as important as *what* was done.
|
||||
|
||||
You can think of a test as being broken down into four steps:
|
||||
|
||||
1. **Arrange**
|
||||
2. **Act**
|
||||
3. **Assert**
|
||||
4. **Cleanup**
|
||||
|
||||
**Arrange** is where we prepare everything for our test. This means pretty
|
||||
much everything except for the "**act**". It's lining up the dominoes so that
|
||||
the **act** can do its thing in one, state-changing step. This can mean
|
||||
preparing objects, starting/killing services, entering records into a database,
|
||||
or even things like defining a URL to query, generating some credentials for a
|
||||
user that doesn't exist yet, or just waiting for some process to finish.
|
||||
|
||||
**Act** is the singular, state-changing action that kicks off the **behavior**
|
||||
we want to test. This behavior is what carries out the changing of the state of
|
||||
the system under test (SUT), and it's the resulting changed state that we can
|
||||
look at to make a judgement about the behavior. This typically takes the form of
|
||||
a function/method call.
|
||||
|
||||
**Assert** is where we look at that resulting state and check if it looks how
|
||||
we'd expect after the dust has settled. It's where we gather evidence to say the
|
||||
behavior does or does not aligns with what we expect. The ``assert`` in our test
|
||||
is where we take that measurement/observation and apply our judgement to it. If
|
||||
something should be green, we'd say ``assert thing == "green"``.
|
||||
|
||||
**Cleanup** is where the test picks up after itself, so other tests aren't being
|
||||
accidentally influenced by it.
|
||||
|
||||
At its core, the test is ultimately the **act** and **assert** steps, with the
|
||||
**arrange** step only providing the context. **Behavior** exists between **act**
|
||||
and **assert**.
|
||||
158
doc/en/explanation/fixtures.rst
Normal file
158
doc/en/explanation/fixtures.rst
Normal file
@@ -0,0 +1,158 @@
|
||||
.. _about-fixtures:
|
||||
|
||||
About fixtures
|
||||
===============
|
||||
|
||||
.. seealso:: :ref:`how-to-fixtures`
|
||||
.. seealso:: :ref:`Fixtures reference <reference-fixtures>`
|
||||
|
||||
pytest fixtures are designed to be explicit, modular and scalable.
|
||||
|
||||
What fixtures are
|
||||
-----------------
|
||||
|
||||
In testing, a `fixture <https://en.wikipedia.org/wiki/Test_fixture#Software>`_
|
||||
provides a defined, reliable and consistent context for the tests. This could
|
||||
include environment (for example a database configured with known parameters)
|
||||
or content (such as a dataset).
|
||||
|
||||
Fixtures define the steps and data that constitute the *arrange* phase of a
|
||||
test (see :ref:`test-anatomy`). In pytest, they are functions you define that
|
||||
serve this purpose. They can also be used to define a test's *act* phase; this
|
||||
is a powerful technique for designing more complex tests.
|
||||
|
||||
The services, state, or other operating environments set up by fixtures are
|
||||
accessed by test functions through arguments. For each fixture used by a test
|
||||
function there is typically a parameter (named after the fixture) in the test
|
||||
function's definition.
|
||||
|
||||
We can tell pytest that a particular function is a fixture by decorating it with
|
||||
:py:func:`@pytest.fixture <pytest.fixture>`. Here's a simple example of
|
||||
what a fixture in pytest might look like:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class Fruit:
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
def __eq__(self, other):
|
||||
return self.name == other.name
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def my_fruit():
|
||||
return Fruit("apple")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def fruit_basket(my_fruit):
|
||||
return [Fruit("banana"), my_fruit]
|
||||
|
||||
|
||||
def test_my_fruit_in_basket(my_fruit, fruit_basket):
|
||||
assert my_fruit in fruit_basket
|
||||
|
||||
Tests don't have to be limited to a single fixture, either. They can depend on
|
||||
as many fixtures as you want, and fixtures can use other fixtures, as well. This
|
||||
is where pytest's fixture system really shines.
|
||||
|
||||
|
||||
Improvements over xUnit-style setup/teardown functions
|
||||
-----------------------------------------------------------
|
||||
|
||||
pytest fixtures offer dramatic improvements over the classic xUnit
|
||||
style of setup/teardown functions:
|
||||
|
||||
* fixtures have explicit names and are activated by declaring their use
|
||||
from test functions, modules, classes or whole projects.
|
||||
|
||||
* fixtures are implemented in a modular manner, as each fixture name
|
||||
triggers a *fixture function* which can itself use other fixtures.
|
||||
|
||||
* fixture management scales from simple unit to complex
|
||||
functional testing, allowing to parametrize fixtures and tests according
|
||||
to configuration and component options, or to re-use fixtures
|
||||
across function, class, module or whole test session scopes.
|
||||
|
||||
* teardown logic can be easily, and safely managed, no matter how many fixtures
|
||||
are used, without the need to carefully handle errors by hand or micromanage
|
||||
the order that cleanup steps are added.
|
||||
|
||||
In addition, pytest continues to support :ref:`xunitsetup`. You can mix
|
||||
both styles, moving incrementally from classic to new style, as you
|
||||
prefer. You can also start out from existing :ref:`unittest.TestCase
|
||||
style <unittest.TestCase>` or :ref:`nose based <nosestyle>` projects.
|
||||
|
||||
|
||||
|
||||
Fixture errors
|
||||
--------------
|
||||
|
||||
pytest does its best to put all the fixtures for a given test in a linear order
|
||||
so that it can see which fixture happens first, second, third, and so on. If an
|
||||
earlier fixture has a problem, though, and raises an exception, pytest will stop
|
||||
executing fixtures for that test and mark the test as having an error.
|
||||
|
||||
When a test is marked as having an error, it doesn't mean the test failed,
|
||||
though. It just means the test couldn't even be attempted because one of the
|
||||
things it depends on had a problem.
|
||||
|
||||
This is one reason why it's a good idea to cut out as many unnecessary
|
||||
dependencies as possible for a given test. That way a problem in something
|
||||
unrelated isn't causing us to have an incomplete picture of what may or may not
|
||||
have issues.
|
||||
|
||||
Here's a quick example to help explain:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def order():
|
||||
return []
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def append_first(order):
|
||||
order.append(1)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def append_second(order, append_first):
|
||||
order.extend([2])
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def append_third(order, append_second):
|
||||
order += [3]
|
||||
|
||||
|
||||
def test_order(order):
|
||||
assert order == [1, 2, 3]
|
||||
|
||||
|
||||
If, for whatever reason, ``order.append(1)`` had a bug and it raises an exception,
|
||||
we wouldn't be able to know if ``order.extend([2])`` or ``order += [3]`` would
|
||||
also have problems. After ``append_first`` throws an exception, pytest won't run
|
||||
any more fixtures for ``test_order``, and it won't even try to run
|
||||
``test_order`` itself. The only things that would've run would be ``order`` and
|
||||
``append_first``.
|
||||
|
||||
|
||||
Sharing test data
|
||||
-----------------
|
||||
|
||||
If you want to make test data from files available to your tests, a good way
|
||||
to do this is by loading these data in a fixture for use by your tests.
|
||||
This makes use of the automatic caching mechanisms of pytest.
|
||||
|
||||
Another good approach is by adding the data files in the ``tests`` folder.
|
||||
There are also community plugins available to help to manage this aspect of
|
||||
testing, e.g. `pytest-datadir <https://pypi.org/project/pytest-datadir/>`__
|
||||
and `pytest-datafiles <https://pypi.org/project/pytest-datafiles/>`__.
|
||||
@@ -113,7 +113,7 @@ Resources
|
||||
|
||||
* `Eradicating Non-Determinism in Tests <https://martinfowler.com/articles/nonDeterminism.html>`_ by Martin Fowler, 2011
|
||||
* `No more flaky tests on the Go team <https://www.thoughtworks.com/insights/blog/no-more-flaky-tests-go-team>`_ by Pavan Sudarshan, 2012
|
||||
* `The Build That Cried Broken: Building Trust in your Continuous Integration Tests <https://www.youtube.com/embed/VotJqV4n8ig>`_ talk (video) by `Angie Jones <http://angiejones.tech/>`_ at SeleniumConf Austin 2017
|
||||
* `The Build That Cried Broken: Building Trust in your Continuous Integration Tests <https://www.youtube.com/embed/VotJqV4n8ig>`_ talk (video) by `Angie Jones <https://angiejones.tech/>`_ at SeleniumConf Austin 2017
|
||||
* `Test and Code Podcast: Flaky Tests and How to Deal with Them <https://testandcode.com/50>`_ by Brian Okken and Anthony Shaw, 2018
|
||||
* Microsoft:
|
||||
|
||||
@@ -48,7 +48,7 @@ Conventions for Python test discovery
|
||||
* ``test`` prefixed test functions or methods outside of class
|
||||
* ``test`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)
|
||||
|
||||
For examples of how to customize your test discovery :doc:`example/pythoncollection`.
|
||||
For examples of how to customize your test discovery :doc:`/example/pythoncollection`.
|
||||
|
||||
Within Python modules, ``pytest`` also discovers tests using the standard
|
||||
:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
|
||||
@@ -151,7 +151,7 @@ This layout prevents a lot of common pitfalls and has many benefits, which are b
|
||||
|
||||
.. note::
|
||||
The new ``--import-mode=importlib`` (see :ref:`import-modes`) doesn't have
|
||||
any of the drawbacks above because ``sys.path`` and ``sys.modules`` are not changed when importing
|
||||
any of the drawbacks above because ``sys.path`` is not changed when importing
|
||||
test modules, so users that run
|
||||
into this issue are strongly encouraged to try it and report if the new option works well for them.
|
||||
|
||||
@@ -231,7 +231,7 @@ Note that this layout also works in conjunction with the ``src`` layout mentione
|
||||
|
||||
|
||||
.. _`virtualenv`: https://pypi.org/project/virtualenv/
|
||||
.. _`buildout`: http://www.buildout.org/
|
||||
.. _`buildout`: http://www.buildout.org/en/latest/
|
||||
.. _pip: https://pypi.org/project/pip/
|
||||
|
||||
.. _`use tox`:
|
||||
@@ -240,7 +240,7 @@ tox
|
||||
------
|
||||
|
||||
Once you are done with your work and want to make sure that your actual
|
||||
package passes all tests you may want to look into `tox`_, the
|
||||
package passes all tests you may want to look into `tox <https://tox.readthedocs.io/>`_, the
|
||||
virtualenv test automation tool and its `pytest support
|
||||
<https://tox.readthedocs.io/en/latest/example/pytest.html>`_.
|
||||
tox helps you to setup virtualenv environments with pre-defined
|
||||
15
doc/en/explanation/index.rst
Normal file
15
doc/en/explanation/index.rst
Normal file
@@ -0,0 +1,15 @@
|
||||
:orphan:
|
||||
|
||||
.. _explanation:
|
||||
|
||||
Explanation
|
||||
================
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
anatomy
|
||||
fixtures
|
||||
goodpractices
|
||||
flaky
|
||||
pythonpath
|
||||
@@ -16,14 +16,14 @@ import process can be controlled through the ``--import-mode`` command-line flag
|
||||
these values:
|
||||
|
||||
* ``prepend`` (default): the directory path containing each module will be inserted into the *beginning*
|
||||
of ``sys.path`` if not already there, and then imported with the `__import__ <https://docs.python.org/3/library/functions.html#__import__>`__ builtin.
|
||||
of :py:data:`sys.path` if not already there, and then imported with the `__import__ <https://docs.python.org/3/library/functions.html#__import__>`__ builtin.
|
||||
|
||||
This requires test module names to be unique when the test directory tree is not arranged in
|
||||
packages, because the modules will put in ``sys.modules`` after importing.
|
||||
packages, because the modules will put in :py:data:`sys.modules` after importing.
|
||||
|
||||
This is the classic mechanism, dating back from the time Python 2 was still supported.
|
||||
|
||||
* ``append``: the directory containing each module is appended to the end of ``sys.path`` if not already
|
||||
* ``append``: the directory containing each module is appended to the end of :py:data:`sys.path` if not already
|
||||
there, and imported with ``__import__``.
|
||||
|
||||
This better allows to run test modules against installed versions of a package even if the
|
||||
@@ -41,17 +41,14 @@ these values:
|
||||
we advocate for using :ref:`src <src-layout>` layouts.
|
||||
|
||||
Same as ``prepend``, requires test module names to be unique when the test directory tree is
|
||||
not arranged in packages, because the modules will put in ``sys.modules`` after importing.
|
||||
not arranged in packages, because the modules will put in :py:data:`sys.modules` after importing.
|
||||
|
||||
* ``importlib``: new in pytest-6.0, this mode uses `importlib <https://docs.python.org/3/library/importlib.html>`__ to import test modules. This gives full control over the import process, and doesn't require
|
||||
changing ``sys.path`` or ``sys.modules`` at all.
|
||||
* ``importlib``: new in pytest-6.0, this mode uses `importlib <https://docs.python.org/3/library/importlib.html>`__ to import test modules. This gives full control over the import process, and doesn't require changing :py:data:`sys.path`.
|
||||
|
||||
For this reason this doesn't require test module names to be unique at all, but also makes test
|
||||
modules non-importable by each other. This was made possible in previous modes, for tests not residing
|
||||
in Python packages, because of the side-effects of changing ``sys.path`` and ``sys.modules``
|
||||
mentioned above. Users which require this should turn their tests into proper packages instead.
|
||||
For this reason this doesn't require test module names to be unique, but also makes test
|
||||
modules non-importable by each other.
|
||||
|
||||
We intend to make ``importlib`` the default in future releases.
|
||||
We intend to make ``importlib`` the default in future releases, depending on feedback.
|
||||
|
||||
``prepend`` and ``append`` import modes scenarios
|
||||
-------------------------------------------------
|
||||
@@ -133,4 +130,4 @@ Running pytest with ``pytest [...]`` instead of ``python -m pytest [...]`` yield
|
||||
equivalent behaviour, except that the latter will add the current directory to ``sys.path``, which
|
||||
is standard ``python`` behavior.
|
||||
|
||||
See also :ref:`cmdline`.
|
||||
See also :ref:`invoke-python`.
|
||||
@@ -47,7 +47,7 @@ There are several limitations and difficulties with this approach:
|
||||
2. parametrizing the "db" resource is not straight forward:
|
||||
you need to apply a "parametrize" decorator or implement a
|
||||
:py:func:`~hookspec.pytest_generate_tests` hook
|
||||
calling :py:func:`~python.Metafunc.parametrize` which
|
||||
calling :py:func:`~pytest.Metafunc.parametrize` which
|
||||
performs parametrization at the places where the resource
|
||||
is used. Moreover, you need to modify the factory to use an
|
||||
``extrakey`` parameter containing ``request.param`` to the
|
||||
@@ -113,7 +113,7 @@ This new way of parametrizing funcarg factories should in many cases
|
||||
allow to re-use already written factories because effectively
|
||||
``request.param`` was already used when test functions/classes were
|
||||
parametrized via
|
||||
:py:func:`metafunc.parametrize(indirect=True) <_pytest.python.Metafunc.parametrize>` calls.
|
||||
:py:func:`metafunc.parametrize(indirect=True) <pytest.Metafunc.parametrize>` calls.
|
||||
|
||||
Of course it's perfectly fine to combine parametrization and scoping:
|
||||
|
||||
@@ -168,7 +168,7 @@ pytest for a long time offered a pytest_configure and a pytest_sessionstart
|
||||
hook which are often used to setup global resources. This suffers from
|
||||
several problems:
|
||||
|
||||
1. in distributed testing the master process would setup test resources
|
||||
1. in distributed testing the managing process would setup test resources
|
||||
that are never needed because it only co-ordinates the test run
|
||||
activities of the worker processes.
|
||||
|
||||
|
||||
@@ -1,22 +1,16 @@
|
||||
Installation and Getting Started
|
||||
.. _get-started:
|
||||
|
||||
Get Started
|
||||
===================================
|
||||
|
||||
**Pythons**: Python 3.6, 3.7, 3.8, 3.9, PyPy3
|
||||
|
||||
**Platforms**: Linux and Windows
|
||||
|
||||
**PyPI package name**: `pytest <https://pypi.org/project/pytest/>`_
|
||||
|
||||
**Documentation as PDF**: `download latest <https://media.readthedocs.org/pdf/pytest/latest/pytest.pdf>`_
|
||||
|
||||
``pytest`` is a framework that makes building simple and scalable tests easy. Tests are expressive and readable—no boilerplate code required. Get started in minutes with a small unit test or complex functional test for your application or library.
|
||||
|
||||
.. _`getstarted`:
|
||||
.. _`installation`:
|
||||
|
||||
Install ``pytest``
|
||||
----------------------------------------
|
||||
|
||||
``pytest`` requires: Python 3.6, 3.7, 3.8, 3.9, or PyPy3.
|
||||
|
||||
1. Run the following command in your command line:
|
||||
|
||||
.. code-block:: bash
|
||||
@@ -28,14 +22,14 @@ Install ``pytest``
|
||||
.. code-block:: bash
|
||||
|
||||
$ pytest --version
|
||||
pytest 6.2.2
|
||||
pytest 6.2.4
|
||||
|
||||
.. _`simpletest`:
|
||||
|
||||
Create your first test
|
||||
----------------------------------------------------------
|
||||
|
||||
Create a simple test function with just four lines of code:
|
||||
Create a new file called ``test_sample.py``, containing a function, and a test:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -47,7 +41,7 @@ Create a simple test function with just four lines of code:
|
||||
def test_answer():
|
||||
assert func(3) == 5
|
||||
|
||||
That’s it. You can now execute the test function:
|
||||
The test
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
@@ -77,7 +71,7 @@ The ``[100%]`` refers to the overall progress of running all test cases. After i
|
||||
|
||||
.. note::
|
||||
|
||||
You can use the ``assert`` statement to verify test expectations. pytest’s `Advanced assertion introspection <http://docs.python.org/reference/simple_stmts.html#the-assert-statement>`_ will intelligently report intermediate values of the assert expression so you can avoid the many names `of JUnit legacy methods <http://docs.python.org/library/unittest.html#test-cases>`_.
|
||||
You can use the ``assert`` statement to verify test expectations. pytest’s `Advanced assertion introspection <https://docs.python.org/reference/simple_stmts.html>`_ will intelligently report intermediate values of the assert expression so you can avoid the many names `of JUnit legacy methods <https://docs.python.org/library/unittest.html>`_.
|
||||
|
||||
Run multiple tests
|
||||
----------------------------------------------------------
|
||||
@@ -175,40 +169,36 @@ This is outlined below:
|
||||
|
||||
# content of test_class_demo.py
|
||||
class TestClassDemoInstance:
|
||||
value = 0
|
||||
|
||||
def test_one(self):
|
||||
assert 0
|
||||
self.value = 1
|
||||
assert self.value == 1
|
||||
|
||||
def test_two(self):
|
||||
assert 0
|
||||
assert self.value == 1
|
||||
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -k TestClassDemoInstance -q
|
||||
FF [100%]
|
||||
.F [100%]
|
||||
================================= FAILURES =================================
|
||||
______________________ TestClassDemoInstance.test_one ______________________
|
||||
|
||||
self = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef>
|
||||
|
||||
def test_one(self):
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_class_demo.py:3: AssertionError
|
||||
______________________ TestClassDemoInstance.test_two ______________________
|
||||
|
||||
self = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef>
|
||||
|
||||
def test_two(self):
|
||||
> assert 0
|
||||
E assert 0
|
||||
> assert self.value == 1
|
||||
E assert 0 == 1
|
||||
E + where 0 = <test_class_demo.TestClassDemoInstance object at 0xdeadbeef>.value
|
||||
|
||||
test_class_demo.py:6: AssertionError
|
||||
test_class_demo.py:9: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_class_demo.py::TestClassDemoInstance::test_one - assert 0
|
||||
FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0
|
||||
2 failed in 0.12s
|
||||
FAILED test_class_demo.py::TestClassDemoInstance::test_two - assert 0 == 1
|
||||
1 failed, 1 passed in 0.04s
|
||||
|
||||
Note that attributes added at class level are *class attributes*, so they will be shared between tests.
|
||||
|
||||
Request a unique temporary directory for functional tests
|
||||
--------------------------------------------------------------
|
||||
@@ -217,24 +207,24 @@ Request a unique temporary directory for functional tests
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_tmpdir.py
|
||||
def test_needsfiles(tmpdir):
|
||||
print(tmpdir)
|
||||
# content of test_tmp_path.py
|
||||
def test_needsfiles(tmp_path):
|
||||
print(tmp_path)
|
||||
assert 0
|
||||
|
||||
List the name ``tmpdir`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:
|
||||
List the name ``tmp_path`` in the test function signature and ``pytest`` will lookup and call a fixture factory to create the resource before performing the test function call. Before the test runs, ``pytest`` creates a unique-per-test-invocation temporary directory:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -q test_tmpdir.py
|
||||
$ pytest -q test_tmp_path.py
|
||||
F [100%]
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_needsfiles ______________________________
|
||||
|
||||
tmpdir = local('PYTEST_TMPDIR/test_needsfiles0')
|
||||
tmp_path = Path('PYTEST_TMPDIR/test_needsfiles0')
|
||||
|
||||
def test_needsfiles(tmpdir):
|
||||
print(tmpdir)
|
||||
def test_needsfiles(tmp_path):
|
||||
print(tmp_path)
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
@@ -242,10 +232,10 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
PYTEST_TMPDIR/test_needsfiles0
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_tmpdir.py::test_needsfiles - assert 0
|
||||
FAILED test_tmp_path.py::test_needsfiles - assert 0
|
||||
1 failed in 0.12s
|
||||
|
||||
More info on tmpdir handling is available at :ref:`Temporary directories and files <tmpdir handling>`.
|
||||
More info on temporary directory handling is available at :ref:`Temporary directories and files <tmpdir handling>`.
|
||||
|
||||
Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the command:
|
||||
|
||||
@@ -260,7 +250,7 @@ Continue reading
|
||||
|
||||
Check out additional pytest resources to help you customize tests for your unique workflow:
|
||||
|
||||
* ":ref:`cmdline`" for command line invocation examples
|
||||
* ":ref:`usage`" for command line invocation examples
|
||||
* ":ref:`existingtestsuite`" for working with pre-existing tests
|
||||
* ":ref:`mark`" for information on the ``pytest.mark`` mechanism
|
||||
* ":ref:`fixtures`" for providing a functional baseline to your tests
|
||||
|
||||
147
doc/en/history.rst
Normal file
147
doc/en/history.rst
Normal file
@@ -0,0 +1,147 @@
|
||||
History
|
||||
=======
|
||||
|
||||
pytest has a long and interesting history. The `first commit
|
||||
<https://github.com/pytest-dev/pytest/commit/5992a8ef21424d7571305a8d7e2a3431ee7e1e23>`__
|
||||
in this repository is from January 2007, and even that commit alone already
|
||||
tells a lot: The repository originally was from the `py
|
||||
<https://pypi.org/project/py/>`__ library (later split off to pytest), and it
|
||||
originally was a SVN revision, migrated to Mercurial, and finally migrated to
|
||||
git.
|
||||
|
||||
However, the commit says “create the new development trunk” and is
|
||||
already quite big: *435 files changed, 58640 insertions(+)*. This is because
|
||||
pytest originally was born as part of `PyPy <https://www.pypy.org/>`__, to make
|
||||
it easier to write tests for it. Here's how it evolved from there to its own
|
||||
project:
|
||||
|
||||
|
||||
- Late 2002 / early 2003, `PyPy was
|
||||
born <https://morepypy.blogspot.com/2018/09/the-first-15-years-of-pypy.html>`__.
|
||||
- Like that blog post mentioned, from very early on, there was a big
|
||||
focus on testing. There were various ``testsupport`` files on top of
|
||||
unittest.py, and as early as June 2003, Holger Krekel (`@hpk42 <https://github.com/hpk42>`__)
|
||||
`refactored <https://mail.python.org/pipermail/pypy-dev/2003-June/000787.html>`__
|
||||
its test framework to clean things up (``pypy.tool.test``, but still
|
||||
on top of ``unittest.py``, with nothing pytest-like yet).
|
||||
- In December 2003, there was `another
|
||||
iteration <https://foss.heptapod.net/pypy/pypy/-/commit/02752373e1b29d89c6bb0a97e5f940caa22bdd63>`__
|
||||
at improving their testing situation, by Stefan Schwarzer, called
|
||||
``pypy.tool.newtest``.
|
||||
- However, it didn’t seem to be around for long, as around June/July
|
||||
2004, efforts started on a thing called ``utest``, offering plain
|
||||
assertions. This seems like the start of something pytest-like, but
|
||||
unfortunately, it's unclear where the test runner's code was at the time.
|
||||
The closest thing still around is `this
|
||||
file <https://foss.heptapod.net/pypy/pypy/-/commit/0735f9ed287ec20950a7dd0a16fc10810d4f6847>`__,
|
||||
but that doesn’t seem like a complete test runner at all. What can be seen
|
||||
is that there were `various
|
||||
efforts <https://foss.heptapod.net/pypy/pypy/-/commits/branch/default?utf8=%E2%9C%93&search=utest>`__
|
||||
by Laura Creighton and Samuele Pedroni (`@pedronis <https://github.com/pedronis>`__) at automatically
|
||||
converting existing tests to the new ``utest`` framework.
|
||||
- Around the same time, for Europython 2004, @hpk42 `started a
|
||||
project <http://web.archive.org/web/20041020215353/http://codespeak.net/svn/user/hpk/talks/std-talk.txt>`__
|
||||
originally called “std”, intended to be a “complementary standard
|
||||
library” - already laying out the principles behind what later became
|
||||
pytest:
|
||||
|
||||
- current “batteries included” are very useful, but
|
||||
|
||||
- some of them are written in a pretty much java-like style,
|
||||
especially the unittest-framework
|
||||
- […]
|
||||
- the best API is one that doesn’t exist
|
||||
|
||||
[…]
|
||||
|
||||
- a testing package should require as few boilerplate code as
|
||||
possible and offer much flexibility
|
||||
- it should provide premium quality tracebacks and debugging aid
|
||||
|
||||
[…]
|
||||
|
||||
- first of all … forget about limited “assertXYZ APIs” and use the
|
||||
real thing, e.g.::
|
||||
|
||||
assert x == y
|
||||
|
||||
- this works with plain python but you get unhelpful “assertion
|
||||
failed” errors with no information
|
||||
|
||||
- std.utest (magic!) actually reinterprets the assertion expression
|
||||
and offers detailed information about underlying values
|
||||
|
||||
- In September 2004, the ``py-dev`` mailinglist gets born, which `is
|
||||
now <https://mail.python.org/pipermail/pytest-dev/>`__ ``pytest-dev``,
|
||||
but thankfully with all the original archives still intact.
|
||||
|
||||
- Around September/October 2004, the ``std`` project `was renamed
|
||||
<https://mail.python.org/pipermail/pypy-dev/2004-September/001565.html>`__ to
|
||||
``py`` and ``std.utest`` became ``py.test``. This is also the first time the
|
||||
`entire source
|
||||
code <https://foss.heptapod.net/pypy/pypy/-/commit/42cf50c412026028e20acd23d518bd92e623ac11>`__,
|
||||
seems to be available, with much of the API still being around today:
|
||||
|
||||
- ``py.path.local``, which is being phased out of pytest (in favour of
|
||||
pathlib) some 16-17 years later
|
||||
- The idea of the collection tree, including ``Collector``,
|
||||
``FSCollector``, ``Directory``, ``PyCollector``, ``Module``,
|
||||
``Class``
|
||||
- Arguments like ``-x`` / ``--exitfirst``, ``-l`` /
|
||||
``--showlocals``, ``--fulltrace``, ``--pdb``, ``-S`` /
|
||||
``--nocapture`` (``-s`` / ``--capture=off`` today),
|
||||
``--collectonly`` (``--collect-only`` today)
|
||||
|
||||
- In the same month, the ``py`` library `gets split off
|
||||
<https://foss.heptapod.net/pypy/pypy/-/commit/6bdafe9203ad92eb259270b267189141c53bce33>`__
|
||||
from ``PyPy``
|
||||
|
||||
- It seemed to get rather quiet for a while, and little seemed to happen
|
||||
between October 2004 (removing ``py`` from PyPy) and January
|
||||
2007 (first commit in the now-pytest repository). However, there were
|
||||
various discussions about features/ideas on the mailinglist, and `a
|
||||
couple of
|
||||
releases <https://pypi.org/project/py/0.8.0-alpha2/#history>`__ every
|
||||
couple of months:
|
||||
|
||||
- March 2006: py 0.8.0-alpha2
|
||||
- May 2007: py 0.9.0
|
||||
- March 2008: py 0.9.1 (first release to be found `in the pytest
|
||||
changelog <https://github.com/pytest-dev/pytest/blob/main/doc/en/changelog.rst#091>`__!)
|
||||
- August 2008: py 0.9.2
|
||||
|
||||
- In August 2009, py 1.0.0 was released, `introducing a lot of
|
||||
fundamental
|
||||
features <https://holgerkrekel.net/2009/08/04/pylib-1-0-0-released-the-testing-with-python-innovations-continue/>`__:
|
||||
|
||||
- funcargs/fixtures
|
||||
- A `plugin
|
||||
architecture <http://web.archive.org/web/20090629032718/https://codespeak.net/py/dist/test/extend.html>`__
|
||||
which still looks very much the same today!
|
||||
- Various `default
|
||||
plugins <http://web.archive.org/web/20091005181132/https://codespeak.net/py/dist/test/plugin/index.html>`__,
|
||||
including
|
||||
`monkeypatch <http://web.archive.org/web/20091012022829/http://codespeak.net/py/dist/test/plugin/monkeypatch.html>`__
|
||||
|
||||
- Even back there, the
|
||||
`FAQ <http://web.archive.org/web/20091005222413/http://codespeak.net/py/dist/faq.html>`__
|
||||
said:
|
||||
|
||||
Clearly, [a second standard library] was ambitious and the naming has
|
||||
maybe haunted the project rather than helping it. There may be a
|
||||
project name change and possibly a split up into different projects
|
||||
sometime.
|
||||
|
||||
and that finally happened in November 2010, when pytest 2.0.0 `was
|
||||
released <https://mail.python.org/pipermail/pytest-dev/2010-November/001687.html>`__
|
||||
as a package separate from ``py`` (but still called ``py.test``).
|
||||
|
||||
- In August 2016, pytest 3.0.0 `was
|
||||
released <https://docs.pytest.org/en/latest/changelog.html#id1313>`__,
|
||||
which adds ``pytest`` (rather than ``py.test``) as the recommended
|
||||
command-line entry point
|
||||
|
||||
Due to this history, it's diffcult to answer the question when pytest was started.
|
||||
It depends what point should really be seen as the start of it all. One
|
||||
possible interpretation is to pick Europython 2004, i.e. around June/July
|
||||
2004.
|
||||
@@ -1,16 +1,14 @@
|
||||
|
||||
The writing and reporting of assertions in tests
|
||||
==================================================
|
||||
|
||||
.. _`assertfeedback`:
|
||||
.. _`assert with the assert statement`:
|
||||
.. _`assert`:
|
||||
|
||||
How to write and report assertions in tests
|
||||
==================================================
|
||||
|
||||
.. _`assert with the assert statement`:
|
||||
|
||||
Asserting with the ``assert`` statement
|
||||
---------------------------------------------------------
|
||||
|
||||
``pytest`` allows you to use the standard python ``assert`` for verifying
|
||||
``pytest`` allows you to use the standard Python ``assert`` for verifying
|
||||
expectations and values in Python tests. For example, you can write the
|
||||
following:
|
||||
|
||||
@@ -98,7 +96,7 @@ and if you need to have access to the actual exception info you may use:
|
||||
f()
|
||||
assert "maximum recursion" in str(excinfo.value)
|
||||
|
||||
``excinfo`` is an ``ExceptionInfo`` instance, which is a wrapper around
|
||||
``excinfo`` is an :class:`~pytest.ExceptionInfo` instance, which is a wrapper around
|
||||
the actual exception raised. The main attributes of interest are
|
||||
``.type``, ``.value`` and ``.traceback``.
|
||||
|
||||
@@ -175,8 +173,6 @@ when it encounters comparisons. For example:
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_assert2.py
|
||||
|
||||
|
||||
def test_set_comparison():
|
||||
set1 = set("1308")
|
||||
set2 = set("8035")
|
||||
@@ -1,8 +1,8 @@
|
||||
|
||||
.. _bash_completion:
|
||||
|
||||
Setting up bash completion
|
||||
==========================
|
||||
How to set up bash completion
|
||||
=============================
|
||||
|
||||
When using bash as your shell, ``pytest`` can use argcomplete
|
||||
(https://argcomplete.readthedocs.io/) for auto-completion.
|
||||
@@ -2,8 +2,8 @@
|
||||
.. _cache:
|
||||
|
||||
|
||||
Cache: working with cross-testrun state
|
||||
=======================================
|
||||
How to re-run failed tests and maintain state between test runs
|
||||
===============================================================
|
||||
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
.. _`captures`:
|
||||
|
||||
Capturing of the stdout/stderr output
|
||||
How to capture stdout/stderr output
|
||||
=========================================================
|
||||
|
||||
Default stdout/stderr/stdin capturing behaviour
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _`warnings`:
|
||||
|
||||
Warnings Capture
|
||||
================
|
||||
How to capture warnings
|
||||
=======================
|
||||
|
||||
|
||||
|
||||
@@ -173,8 +173,6 @@ DeprecationWarning and PendingDeprecationWarning
|
||||
------------------------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
By default pytest will display ``DeprecationWarning`` and ``PendingDeprecationWarning`` warnings from
|
||||
user code and third-party libraries, as recommended by `PEP-0565 <https://www.python.org/dev/peps/pep-0565>`_.
|
||||
This helps users keep their code modern and avoid breakages when deprecated warnings are effectively removed.
|
||||
@@ -230,27 +228,8 @@ that a certain function call triggers a ``DeprecationWarning`` or
|
||||
This test will fail if ``myfunction`` does not issue a deprecation warning
|
||||
when called with a ``17`` argument.
|
||||
|
||||
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
||||
caught when using :func:`pytest.warns` or :ref:`recwarn <recwarn>` because
|
||||
the default Python warnings filters hide
|
||||
them. If you wish to record them in your own code, use
|
||||
``warnings.simplefilter('always')``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
|
||||
def test_deprecation(recwarn):
|
||||
warnings.simplefilter("always")
|
||||
myfunction(17)
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
|
||||
The :ref:`recwarn <recwarn>` fixture automatically ensures to reset the warnings
|
||||
filter at the end of the test, so no global state is leaked.
|
||||
|
||||
.. _`asserting warnings`:
|
||||
|
||||
@@ -265,7 +244,7 @@ Asserting warnings with the warns function
|
||||
|
||||
|
||||
|
||||
You can check that code raises a particular warning using func:`pytest.warns`,
|
||||
You can check that code raises a particular warning using :func:`pytest.warns`,
|
||||
which works in a similar manner to :ref:`raises <assertraises>`:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -293,7 +272,7 @@ argument ``match`` to assert that the exception matches a text or regex::
|
||||
...
|
||||
Failed: DID NOT WARN. No warnings of type ...UserWarning... was emitted...
|
||||
|
||||
You can also call func:`pytest.warns` on a function or code string:
|
||||
You can also call :func:`pytest.warns` on a function or code string:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -317,9 +296,9 @@ additional information:
|
||||
Alternatively, you can examine raised warnings in detail using the
|
||||
:ref:`recwarn <recwarn>` fixture (see below).
|
||||
|
||||
.. note::
|
||||
``DeprecationWarning`` and ``PendingDeprecationWarning`` are treated
|
||||
differently; see :ref:`ensuring_function_triggers`.
|
||||
|
||||
The :ref:`recwarn <recwarn>` fixture automatically ensures to reset the warnings
|
||||
filter at the end of the test, so no global state is leaked.
|
||||
|
||||
.. _`recording warnings`:
|
||||
|
||||
@@ -328,15 +307,15 @@ Alternatively, you can examine raised warnings in detail using the
|
||||
Recording warnings
|
||||
------------------
|
||||
|
||||
You can record raised warnings either using func:`pytest.warns` or with
|
||||
You can record raised warnings either using :func:`pytest.warns` or with
|
||||
the ``recwarn`` fixture.
|
||||
|
||||
To record with func:`pytest.warns` without asserting anything about the warnings,
|
||||
pass ``None`` as the expected warning type:
|
||||
To record with :func:`pytest.warns` without asserting anything about the warnings,
|
||||
pass no arguments as the expected warning type and it will default to a generic Warning:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with pytest.warns(None) as record:
|
||||
with pytest.warns() as record:
|
||||
warnings.warn("user", UserWarning)
|
||||
warnings.warn("runtime", RuntimeWarning)
|
||||
|
||||
@@ -360,7 +339,7 @@ The ``recwarn`` fixture will record warnings for the whole function:
|
||||
assert w.filename
|
||||
assert w.lineno
|
||||
|
||||
Both ``recwarn`` and func:`pytest.warns` return the same interface for recorded
|
||||
Both ``recwarn`` and :func:`pytest.warns` return the same interface for recorded
|
||||
warnings: a WarningsRecorder instance. To view the recorded warnings, you can
|
||||
iterate over this instance, call ``len`` on it to get the number of recorded
|
||||
warnings, or index into it to get a particular recorded warning.
|
||||
@@ -1,5 +1,6 @@
|
||||
.. _doctest:
|
||||
|
||||
Doctest integration for modules and test files
|
||||
How to run doctests
|
||||
=========================================================
|
||||
|
||||
By default, all files matching the ``test*.txt`` pattern will
|
||||
@@ -48,7 +49,7 @@ and functions, including from test modules:
|
||||
|
||||
# content of mymodule.py
|
||||
def something():
|
||||
""" a doctest in a docstring
|
||||
"""a doctest in a docstring
|
||||
>>> something()
|
||||
42
|
||||
"""
|
||||
@@ -193,7 +194,7 @@ It is possible to use fixtures using the ``getfixture`` helper:
|
||||
.. code-block:: text
|
||||
|
||||
# content of example.rst
|
||||
>>> tmp = getfixture('tmpdir')
|
||||
>>> tmp = getfixture('tmp_path')
|
||||
>>> ...
|
||||
>>>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _existingtestsuite:
|
||||
|
||||
Using pytest with an existing test suite
|
||||
===========================================
|
||||
How to use pytest with an existing test suite
|
||||
==============================================
|
||||
|
||||
Pytest can be used with most existing test suites, but its
|
||||
behavior differs from other test runners such as :ref:`nose <noseintegration>` or
|
||||
162
doc/en/how-to/failures.rst
Normal file
162
doc/en/how-to/failures.rst
Normal file
@@ -0,0 +1,162 @@
|
||||
.. _how-to-handle-failures:
|
||||
|
||||
How to handle test failures
|
||||
=============================
|
||||
|
||||
.. _maxfail:
|
||||
|
||||
Stopping after the first (or N) failures
|
||||
---------------------------------------------------
|
||||
|
||||
To stop the testing process after the first (N) failures:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -x # stop after first failure
|
||||
pytest --maxfail=2 # stop after two failures
|
||||
|
||||
|
||||
.. _pdb-option:
|
||||
|
||||
Using PDB_ (Python Debugger) with pytest
|
||||
----------------------------------------------------------
|
||||
|
||||
Dropping to PDB_ (Python Debugger) on failures
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. _PDB: https://docs.python.org/library/pdb.html
|
||||
|
||||
Python comes with a builtin Python debugger called PDB_. ``pytest``
|
||||
allows one to drop into the PDB_ prompt via a command line option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pdb
|
||||
|
||||
This will invoke the Python debugger on every failure (or KeyboardInterrupt).
|
||||
Often you might only want to do this for the first failing test to understand
|
||||
a certain failure situation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -x --pdb # drop to PDB on first failure, then end test session
|
||||
pytest --pdb --maxfail=3 # drop to PDB for first three failures
|
||||
|
||||
Note that on any failure the exception information is stored on
|
||||
``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
|
||||
interactive use, this allows one to drop into postmortem debugging with
|
||||
any debug tool. One can also manually access the exception information,
|
||||
for example::
|
||||
|
||||
>>> import sys
|
||||
>>> sys.last_traceback.tb_lineno
|
||||
42
|
||||
>>> sys.last_value
|
||||
AssertionError('assert result == "ok"',)
|
||||
|
||||
|
||||
.. _trace-option:
|
||||
|
||||
Dropping to PDB_ at the start of a test
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``pytest`` allows one to drop into the PDB_ prompt immediately at the start of each test via a command line option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --trace
|
||||
|
||||
This will invoke the Python debugger at the start of every test.
|
||||
|
||||
.. _breakpoints:
|
||||
|
||||
Setting breakpoints
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. versionadded: 2.4.0
|
||||
|
||||
To set a breakpoint in your code use the native Python ``import pdb;pdb.set_trace()`` call
|
||||
in your code and pytest automatically disables its output capture for that test:
|
||||
|
||||
* Output capture in other tests is not affected.
|
||||
* Any prior test output that has already been captured and will be processed as
|
||||
such.
|
||||
* Output capture gets resumed when ending the debugger session (via the
|
||||
``continue`` command).
|
||||
|
||||
|
||||
.. _`breakpoint-builtin`:
|
||||
|
||||
Using the builtin breakpoint function
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Python 3.7 introduces a builtin ``breakpoint()`` function.
|
||||
Pytest supports the use of ``breakpoint()`` with the following behaviours:
|
||||
|
||||
- When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``.
|
||||
- When tests are complete, the system will default back to the system ``Pdb`` trace UI.
|
||||
- With ``--pdb`` passed to pytest, the custom internal Pdb trace UI is used with both ``breakpoint()`` and failed tests/unhandled exceptions.
|
||||
- ``--pdbcls`` can be used to specify a custom debugger class.
|
||||
|
||||
|
||||
.. _faulthandler:
|
||||
|
||||
Fault Handler
|
||||
-------------
|
||||
|
||||
.. versionadded:: 5.0
|
||||
|
||||
The `faulthandler <https://docs.python.org/3/library/faulthandler.html>`__ standard module
|
||||
can be used to dump Python tracebacks on a segfault or after a timeout.
|
||||
|
||||
The module is automatically enabled for pytest runs, unless the ``-p no:faulthandler`` is given
|
||||
on the command-line.
|
||||
|
||||
Also the :confval:`faulthandler_timeout=X<faulthandler_timeout>` configuration option can be used
|
||||
to dump the traceback of all threads if a test takes longer than ``X``
|
||||
seconds to finish (not available on Windows).
|
||||
|
||||
.. note::
|
||||
|
||||
This functionality has been integrated from the external
|
||||
`pytest-faulthandler <https://github.com/pytest-dev/pytest-faulthandler>`__ plugin, with two
|
||||
small differences:
|
||||
|
||||
* To disable it, use ``-p no:faulthandler`` instead of ``--no-faulthandler``: the former
|
||||
can be used with any plugin, so it saves one option.
|
||||
|
||||
* The ``--faulthandler-timeout`` command-line option has become the
|
||||
:confval:`faulthandler_timeout` configuration option. It can still be configured from
|
||||
the command-line using ``-o faulthandler_timeout=X``.
|
||||
|
||||
|
||||
.. _unraisable:
|
||||
|
||||
Warning about unraisable exceptions and unhandled thread exceptions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 6.2
|
||||
|
||||
.. note::
|
||||
|
||||
These features only work on Python>=3.8.
|
||||
|
||||
Unhandled exceptions are exceptions that are raised in a situation in which
|
||||
they cannot propagate to a caller. The most common case is an exception raised
|
||||
in a :meth:`__del__ <object.__del__>` implementation.
|
||||
|
||||
Unhandled thread exceptions are exceptions raised in a :class:`~threading.Thread`
|
||||
but not handled, causing the thread to terminate uncleanly.
|
||||
|
||||
Both types of exceptions are normally considered bugs, but may go unnoticed
|
||||
because they don't cause the program itself to crash. Pytest detects these
|
||||
conditions and issues a warning that is visible in the test run summary.
|
||||
|
||||
The plugins are automatically enabled for pytest runs, unless the
|
||||
``-p no:unraisableexception`` (for unraisable exceptions) and
|
||||
``-p no:threadexception`` (for thread exceptions) options are given on the
|
||||
command-line.
|
||||
|
||||
The warnings may be silenced selectively using the :ref:`pytest.mark.filterwarnings ref`
|
||||
mark. The warning categories are :class:`pytest.PytestUnraisableExceptionWarning` and
|
||||
:class:`pytest.PytestUnhandledThreadExceptionWarning`.
|
||||
File diff suppressed because it is too large
Load Diff
64
doc/en/how-to/index.rst
Normal file
64
doc/en/how-to/index.rst
Normal file
@@ -0,0 +1,64 @@
|
||||
:orphan:
|
||||
|
||||
.. _how-to:
|
||||
|
||||
How-to guides
|
||||
================
|
||||
|
||||
Core pytest functionality
|
||||
-------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
usage
|
||||
assert
|
||||
fixtures
|
||||
mark
|
||||
parametrize
|
||||
tmpdir
|
||||
monkeypatch
|
||||
doctest
|
||||
cache
|
||||
|
||||
Test output and outcomes
|
||||
----------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
failures
|
||||
output
|
||||
logging
|
||||
capture-stdout-stderr
|
||||
capture-warnings
|
||||
skipping
|
||||
|
||||
Plugins
|
||||
----------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
plugins
|
||||
writing_plugins
|
||||
writing_hook_functions
|
||||
|
||||
pytest and other test systems
|
||||
-----------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
existingtestsuite
|
||||
unittest
|
||||
nose
|
||||
xunit_setup
|
||||
|
||||
pytest development environment
|
||||
------------------------------
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
bash-completion
|
||||
@@ -1,10 +1,7 @@
|
||||
.. _logging:
|
||||
|
||||
Logging
|
||||
-------
|
||||
|
||||
|
||||
|
||||
How to manage logging
|
||||
---------------------
|
||||
|
||||
pytest captures log messages of level ``WARNING`` or above automatically and displays them in their own section
|
||||
for each failed test in the same manner as captured stdout and stderr.
|
||||
@@ -170,7 +167,7 @@ the records for the ``setup`` and ``call`` stages during teardown like so:
|
||||
|
||||
|
||||
|
||||
The full API is available at :class:`_pytest.logging.LogCaptureFixture`.
|
||||
The full API is available at :class:`pytest.LogCaptureFixture`.
|
||||
|
||||
|
||||
.. _live_logs:
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _mark:
|
||||
|
||||
Marking test functions with attributes
|
||||
======================================
|
||||
How to mark test functions with attributes
|
||||
===========================================
|
||||
|
||||
By using the ``pytest.mark`` helper you can easily set
|
||||
metadata on your test functions. You can find the full list of builtin markers
|
||||
@@ -1,5 +1,6 @@
|
||||
.. _monkeypatching:
|
||||
|
||||
Monkeypatching/mocking modules and environments
|
||||
How to monkeypatch/mock modules and environments
|
||||
================================================================
|
||||
|
||||
.. currentmodule:: _pytest.monkeypatch
|
||||
@@ -16,6 +17,7 @@ functionality in tests:
|
||||
.. code-block:: python
|
||||
|
||||
monkeypatch.setattr(obj, name, value, raising=True)
|
||||
monkeypatch.setattr("somemodule.obj.name", value, raising=True)
|
||||
monkeypatch.delattr(obj, name, raising=True)
|
||||
monkeypatch.setitem(mapping, name, value)
|
||||
monkeypatch.delitem(obj, name, raising=True)
|
||||
@@ -56,7 +58,7 @@ call ``pkg_resources.fixup_namespace_packages`` and :py:func:`importlib.invalida
|
||||
See the `monkeypatch blog post`_ for some introduction material
|
||||
and a discussion of its motivation.
|
||||
|
||||
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||
.. _`monkeypatch blog post`: https://tetamap.wordpress.com//2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||
|
||||
Simple example: monkeypatching functions
|
||||
----------------------------------------
|
||||
@@ -1,6 +1,6 @@
|
||||
.. _`noseintegration`:
|
||||
|
||||
Running tests written for nose
|
||||
How to run tests written for nose
|
||||
=======================================
|
||||
|
||||
``pytest`` has basic support for running tests written for nose_.
|
||||
@@ -1,146 +1,10 @@
|
||||
.. _how-to-manage-output:
|
||||
|
||||
.. _usage:
|
||||
|
||||
Usage and Invocations
|
||||
==========================================
|
||||
|
||||
|
||||
.. _cmdline:
|
||||
|
||||
Calling pytest through ``python -m pytest``
|
||||
-----------------------------------------------------
|
||||
|
||||
|
||||
|
||||
You can invoke testing through the Python interpreter from the command line:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
python -m pytest [...]
|
||||
|
||||
This is almost equivalent to invoking the command line script ``pytest [...]``
|
||||
directly, except that calling via ``python`` will also add the current directory to ``sys.path``.
|
||||
|
||||
Possible exit codes
|
||||
--------------------------------------------------------------
|
||||
|
||||
Running ``pytest`` can result in six different exit codes:
|
||||
|
||||
:Exit code 0: All tests were collected and passed successfully
|
||||
:Exit code 1: Tests were collected and run but some of the tests failed
|
||||
:Exit code 2: Test execution was interrupted by the user
|
||||
:Exit code 3: Internal error happened while executing tests
|
||||
:Exit code 4: pytest command line usage error
|
||||
:Exit code 5: No tests were collected
|
||||
|
||||
They are represented by the :class:`pytest.ExitCode` enum. The exit codes being a part of the public API can be imported and accessed directly using:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from pytest import ExitCode
|
||||
|
||||
.. note::
|
||||
|
||||
If you would like to customize the exit code in some scenarios, specially when
|
||||
no tests are collected, consider using the
|
||||
`pytest-custom_exit_code <https://github.com/yashtodi94/pytest-custom_exit_code>`__
|
||||
plugin.
|
||||
|
||||
|
||||
Getting help on version, option names, environment variables
|
||||
--------------------------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --version # shows where pytest was imported from
|
||||
pytest --fixtures # show available builtin function arguments
|
||||
pytest -h | --help # show help on command line and config file options
|
||||
|
||||
|
||||
The full command-line flags can be found in the :ref:`reference <command-line-flags>`.
|
||||
|
||||
.. _maxfail:
|
||||
|
||||
Stopping after the first (or N) failures
|
||||
---------------------------------------------------
|
||||
|
||||
To stop the testing process after the first (N) failures:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -x # stop after first failure
|
||||
pytest --maxfail=2 # stop after two failures
|
||||
|
||||
.. _select-tests:
|
||||
|
||||
Specifying tests / selecting tests
|
||||
---------------------------------------------------
|
||||
|
||||
Pytest supports several ways to run and select tests from the command-line.
|
||||
|
||||
**Run tests in a module**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py
|
||||
|
||||
**Run tests in a directory**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest testing/
|
||||
|
||||
**Run tests by keyword expressions**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -k "MyClass and not method"
|
||||
|
||||
This will run tests which contain names that match the given *string expression* (case-insensitive),
|
||||
which can include Python operators that use filenames, class names and function names as variables.
|
||||
The example above will run ``TestMyClass.test_something`` but not ``TestMyClass.test_method_simple``.
|
||||
|
||||
.. _nodeids:
|
||||
|
||||
**Run tests by node ids**
|
||||
|
||||
Each collected test is assigned a unique ``nodeid`` which consist of the module filename followed
|
||||
by specifiers like class names, function names and parameters from parametrization, separated by ``::`` characters.
|
||||
|
||||
To run a specific test within a module:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py::test_func
|
||||
|
||||
|
||||
Another example specifying a test method in the command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py::TestClass::test_method
|
||||
|
||||
**Run tests by marker expressions**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -m slow
|
||||
|
||||
Will run all tests which are decorated with the ``@pytest.mark.slow`` decorator.
|
||||
|
||||
For more information see :ref:`marks <mark>`.
|
||||
|
||||
**Run tests from packages**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pyargs pkg.testing
|
||||
|
||||
This will import ``pkg.testing`` and use its filesystem location to find and run tests from.
|
||||
|
||||
Managing pytest's output
|
||||
=========================
|
||||
|
||||
Modifying Python traceback printing
|
||||
----------------------------------------------
|
||||
--------------------------------------------------
|
||||
|
||||
Examples for modifying traceback printing:
|
||||
|
||||
@@ -166,16 +30,255 @@ will be shown (because KeyboardInterrupt is caught by pytest). By using this
|
||||
option you make sure a trace is shown.
|
||||
|
||||
|
||||
Verbosity
|
||||
--------------------------------------------------
|
||||
|
||||
The ``-v`` flag controls the verbosity of pytest output in various aspects: test session progress, assertion
|
||||
details when tests fail, fixtures details with ``--fixtures``, etc.
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
Consider this simple file:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_verbosity_example.py
|
||||
def test_ok():
|
||||
pass
|
||||
|
||||
|
||||
def test_words_fail():
|
||||
fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
|
||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||
assert fruits1 == fruits2
|
||||
|
||||
|
||||
def test_numbers_fail():
|
||||
number_to_text1 = {str(x): x for x in range(5)}
|
||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||
assert number_to_text1 == number_to_text2
|
||||
|
||||
|
||||
def test_long_text_fail():
|
||||
long_text = "Lorem ipsum dolor sit amet " * 10
|
||||
assert "hello world" in long_text
|
||||
|
||||
Executing pytest normally gives us this output (we are skipping the header to focus on the rest):
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --no-header
|
||||
=========================== test session starts ===========================
|
||||
collected 4 items
|
||||
|
||||
test_verbosity_example.py .FFF [100%]
|
||||
|
||||
================================ FAILURES =================================
|
||||
_____________________________ test_words_fail _____________________________
|
||||
|
||||
def test_words_fail():
|
||||
fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
|
||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||
> assert fruits1 == fruits2
|
||||
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
||||
E At index 2 diff: 'grapes' != 'orange'
|
||||
E Use -v to get the full diff
|
||||
|
||||
test_verbosity_example.py:8: AssertionError
|
||||
____________________________ test_numbers_fail ____________________________
|
||||
|
||||
def test_numbers_fail():
|
||||
number_to_text1 = {str(x): x for x in range(5)}
|
||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||
> assert number_to_text1 == number_to_text2
|
||||
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
||||
E Omitting 1 identical items, use -vv to show
|
||||
E Left contains 4 more items:
|
||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||
E Right contains 4 more items:
|
||||
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
||||
E Use -v to get the full diff
|
||||
|
||||
test_verbosity_example.py:14: AssertionError
|
||||
___________________________ test_long_text_fail ___________________________
|
||||
|
||||
def test_long_text_fail():
|
||||
long_text = "Lorem ipsum dolor sit amet " * 10
|
||||
> assert "hello world" in long_text
|
||||
E AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ips... sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '
|
||||
|
||||
test_verbosity_example.py:19: AssertionError
|
||||
========================= short test summary info =========================
|
||||
FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser...
|
||||
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass...
|
||||
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a...
|
||||
======================= 3 failed, 1 passed in 0.08s =======================
|
||||
|
||||
Notice that:
|
||||
|
||||
* Each test inside the file is shown by a single character in the output: ``.`` for passing, ``F`` for failure.
|
||||
* ``test_words_fail`` failed, and we are shown a short summary indicating the index 2 of the two lists differ.
|
||||
* ``test_numbers_fail`` failed, and we are shown a summary of left/right differences on dictionary items. Identical items are omitted.
|
||||
* ``test_long_text_fail`` failed, and the right hand side of the ``in`` statement is truncated using ``...```
|
||||
because it is longer than an internal threshold (240 characters currently).
|
||||
|
||||
Now we can increase pytest's verbosity:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --no-header -v
|
||||
=========================== test session starts ===========================
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_verbosity_example.py::test_ok PASSED [ 25%]
|
||||
test_verbosity_example.py::test_words_fail FAILED [ 50%]
|
||||
test_verbosity_example.py::test_numbers_fail FAILED [ 75%]
|
||||
test_verbosity_example.py::test_long_text_fail FAILED [100%]
|
||||
|
||||
================================ FAILURES =================================
|
||||
_____________________________ test_words_fail _____________________________
|
||||
|
||||
def test_words_fail():
|
||||
fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
|
||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||
> assert fruits1 == fruits2
|
||||
E AssertionError: assert ['banana', 'a...elon', 'kiwi'] == ['banana', 'a...elon', 'kiwi']
|
||||
E At index 2 diff: 'grapes' != 'orange'
|
||||
E Full diff:
|
||||
E - ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
||||
E ? ^ ^^
|
||||
E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']
|
||||
E ? ^ ^ +
|
||||
|
||||
test_verbosity_example.py:8: AssertionError
|
||||
____________________________ test_numbers_fail ____________________________
|
||||
|
||||
def test_numbers_fail():
|
||||
number_to_text1 = {str(x): x for x in range(5)}
|
||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||
> assert number_to_text1 == number_to_text2
|
||||
E AssertionError: assert {'0': 0, '1':..., '3': 3, ...} == {'0': 0, '10'...'30': 30, ...}
|
||||
E Omitting 1 identical items, use -vv to show
|
||||
E Left contains 4 more items:
|
||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||
E Right contains 4 more items:
|
||||
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
||||
E Full diff:
|
||||
E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}...
|
||||
E
|
||||
E ...Full output truncated (3 lines hidden), use '-vv' to show
|
||||
|
||||
test_verbosity_example.py:14: AssertionError
|
||||
___________________________ test_long_text_fail ___________________________
|
||||
|
||||
def test_long_text_fail():
|
||||
long_text = "Lorem ipsum dolor sit amet " * 10
|
||||
> assert "hello world" in long_text
|
||||
E AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '
|
||||
|
||||
test_verbosity_example.py:19: AssertionError
|
||||
========================= short test summary info =========================
|
||||
FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser...
|
||||
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass...
|
||||
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a...
|
||||
======================= 3 failed, 1 passed in 0.07s =======================
|
||||
|
||||
Notice now that:
|
||||
|
||||
* Each test inside the file gets its own line in the output.
|
||||
* ``test_words_fail`` now shows the two failing lists in full, in addition to which index differs.
|
||||
* ``test_numbers_fail`` now shows a text diff of the two dictionaries, truncated.
|
||||
* ``test_long_text_fail`` no longer truncates the right hand side of the ``in`` statement, because the internal
|
||||
threshold for truncation is larger now (2400 characters currently).
|
||||
|
||||
Now if we increase verbosity even more:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --no-header -vv
|
||||
=========================== test session starts ===========================
|
||||
collecting ... collected 4 items
|
||||
|
||||
test_verbosity_example.py::test_ok PASSED [ 25%]
|
||||
test_verbosity_example.py::test_words_fail FAILED [ 50%]
|
||||
test_verbosity_example.py::test_numbers_fail FAILED [ 75%]
|
||||
test_verbosity_example.py::test_long_text_fail FAILED [100%]
|
||||
|
||||
================================ FAILURES =================================
|
||||
_____________________________ test_words_fail _____________________________
|
||||
|
||||
def test_words_fail():
|
||||
fruits1 = ["banana", "apple", "grapes", "melon", "kiwi"]
|
||||
fruits2 = ["banana", "apple", "orange", "melon", "kiwi"]
|
||||
> assert fruits1 == fruits2
|
||||
E AssertionError: assert ['banana', 'apple', 'grapes', 'melon', 'kiwi'] == ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
||||
E At index 2 diff: 'grapes' != 'orange'
|
||||
E Full diff:
|
||||
E - ['banana', 'apple', 'orange', 'melon', 'kiwi']
|
||||
E ? ^ ^^
|
||||
E + ['banana', 'apple', 'grapes', 'melon', 'kiwi']
|
||||
E ? ^ ^ +
|
||||
|
||||
test_verbosity_example.py:8: AssertionError
|
||||
____________________________ test_numbers_fail ____________________________
|
||||
|
||||
def test_numbers_fail():
|
||||
number_to_text1 = {str(x): x for x in range(5)}
|
||||
number_to_text2 = {str(x * 10): x * 10 for x in range(5)}
|
||||
> assert number_to_text1 == number_to_text2
|
||||
E AssertionError: assert {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4} == {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
||||
E Common items:
|
||||
E {'0': 0}
|
||||
E Left contains 4 more items:
|
||||
E {'1': 1, '2': 2, '3': 3, '4': 4}
|
||||
E Right contains 4 more items:
|
||||
E {'10': 10, '20': 20, '30': 30, '40': 40}
|
||||
E Full diff:
|
||||
E - {'0': 0, '10': 10, '20': 20, '30': 30, '40': 40}
|
||||
E ? - - - - - - - -
|
||||
E + {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4}
|
||||
|
||||
test_verbosity_example.py:14: AssertionError
|
||||
___________________________ test_long_text_fail ___________________________
|
||||
|
||||
def test_long_text_fail():
|
||||
long_text = "Lorem ipsum dolor sit amet " * 10
|
||||
> assert "hello world" in long_text
|
||||
E AssertionError: assert 'hello world' in 'Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet '
|
||||
|
||||
test_verbosity_example.py:19: AssertionError
|
||||
========================= short test summary info =========================
|
||||
FAILED test_verbosity_example.py::test_words_fail - AssertionError: asser...
|
||||
FAILED test_verbosity_example.py::test_numbers_fail - AssertionError: ass...
|
||||
FAILED test_verbosity_example.py::test_long_text_fail - AssertionError: a...
|
||||
======================= 3 failed, 1 passed in 0.07s =======================
|
||||
|
||||
Notice now that:
|
||||
|
||||
* Each test inside the file gets its own line in the output.
|
||||
* ``test_words_fail`` gives the same output as before in this case.
|
||||
* ``test_numbers_fail`` now shows a full text diff of the two dictionaries.
|
||||
* ``test_long_text_fail`` also doesn't truncate on the right hand side as before, but now pytest won't truncate any
|
||||
text at all, regardless of its size.
|
||||
|
||||
Those were examples of how verbosity affects normal test session output, but verbosity also is used in other
|
||||
situations, for example you are shown even fixtures that start with ``_`` if you use ``pytest --fixtures -v``.
|
||||
|
||||
Using higher verbosity levels (``-vvv``, ``-vvvv``, ...) is supported, but has no effect in pytest itself at the moment,
|
||||
however some plugins might make use of higher verbosity.
|
||||
|
||||
.. _`pytest.detailed_failed_tests_usage`:
|
||||
|
||||
Detailed summary report
|
||||
-----------------------
|
||||
Producing a detailed summary report
|
||||
--------------------------------------------------
|
||||
|
||||
The ``-r`` flag can be used to display a "short test summary info" at the end of the test session,
|
||||
making it easy in large test suites to get a clear picture of all failures, skips, xfails, etc.
|
||||
|
||||
It defaults to ``fE`` to list failures and errors.
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -344,162 +447,30 @@ captured output:
|
||||
PASSED test_example.py::test_ok
|
||||
== 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12s ===
|
||||
|
||||
.. _pdb-option:
|
||||
|
||||
Dropping to PDB_ (Python Debugger) on failures
|
||||
-----------------------------------------------
|
||||
Creating resultlog format files
|
||||
--------------------------------------------------
|
||||
|
||||
.. _PDB: http://docs.python.org/library/pdb.html
|
||||
|
||||
Python comes with a builtin Python debugger called PDB_. ``pytest``
|
||||
allows one to drop into the PDB_ prompt via a command line option:
|
||||
To create plain-text machine-readable result files you can issue:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pdb
|
||||
pytest --resultlog=path
|
||||
|
||||
This will invoke the Python debugger on every failure (or KeyboardInterrupt).
|
||||
Often you might only want to do this for the first failing test to understand
|
||||
a certain failure situation:
|
||||
and look at the content at the ``path`` location. Such files are used e.g.
|
||||
by the `PyPy-test`_ web page to show test results over several revisions.
|
||||
|
||||
.. code-block:: bash
|
||||
.. warning::
|
||||
|
||||
pytest -x --pdb # drop to PDB on first failure, then end test session
|
||||
pytest --pdb --maxfail=3 # drop to PDB for first three failures
|
||||
This option is rarely used and is scheduled for removal in pytest 6.0.
|
||||
|
||||
Note that on any failure the exception information is stored on
|
||||
``sys.last_value``, ``sys.last_type`` and ``sys.last_traceback``. In
|
||||
interactive use, this allows one to drop into postmortem debugging with
|
||||
any debug tool. One can also manually access the exception information,
|
||||
for example::
|
||||
If you use this option, consider using the new `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.
|
||||
|
||||
>>> import sys
|
||||
>>> sys.last_traceback.tb_lineno
|
||||
42
|
||||
>>> sys.last_value
|
||||
AssertionError('assert result == "ok"',)
|
||||
|
||||
.. _trace-option:
|
||||
|
||||
Dropping to PDB_ (Python Debugger) at the start of a test
|
||||
----------------------------------------------------------
|
||||
See `the deprecation docs <https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log>`__
|
||||
for more information.
|
||||
|
||||
|
||||
``pytest`` allows one to drop into the PDB_ prompt immediately at the start of each test via a command line option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --trace
|
||||
|
||||
This will invoke the Python debugger at the start of every test.
|
||||
|
||||
.. _breakpoints:
|
||||
|
||||
Setting breakpoints
|
||||
-------------------
|
||||
|
||||
.. versionadded: 2.4.0
|
||||
|
||||
To set a breakpoint in your code use the native Python ``import pdb;pdb.set_trace()`` call
|
||||
in your code and pytest automatically disables its output capture for that test:
|
||||
|
||||
* Output capture in other tests is not affected.
|
||||
* Any prior test output that has already been captured and will be processed as
|
||||
such.
|
||||
* Output capture gets resumed when ending the debugger session (via the
|
||||
``continue`` command).
|
||||
|
||||
|
||||
.. _`breakpoint-builtin`:
|
||||
|
||||
Using the builtin breakpoint function
|
||||
-------------------------------------
|
||||
|
||||
Python 3.7 introduces a builtin ``breakpoint()`` function.
|
||||
Pytest supports the use of ``breakpoint()`` with the following behaviours:
|
||||
|
||||
- When ``breakpoint()`` is called and ``PYTHONBREAKPOINT`` is set to the default value, pytest will use the custom internal PDB trace UI instead of the system default ``Pdb``.
|
||||
- When tests are complete, the system will default back to the system ``Pdb`` trace UI.
|
||||
- With ``--pdb`` passed to pytest, the custom internal Pdb trace UI is used with both ``breakpoint()`` and failed tests/unhandled exceptions.
|
||||
- ``--pdbcls`` can be used to specify a custom debugger class.
|
||||
|
||||
.. _durations:
|
||||
|
||||
Profiling test execution duration
|
||||
-------------------------------------
|
||||
|
||||
.. versionchanged:: 6.0
|
||||
|
||||
To get a list of the slowest 10 test durations over 1.0s long:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --durations=10 --durations-min=1.0
|
||||
|
||||
By default, pytest will not show test durations that are too small (<0.005s) unless ``-vv`` is passed on the command-line.
|
||||
|
||||
|
||||
.. _faulthandler:
|
||||
|
||||
Fault Handler
|
||||
-------------
|
||||
|
||||
.. versionadded:: 5.0
|
||||
|
||||
The `faulthandler <https://docs.python.org/3/library/faulthandler.html>`__ standard module
|
||||
can be used to dump Python tracebacks on a segfault or after a timeout.
|
||||
|
||||
The module is automatically enabled for pytest runs, unless the ``-p no:faulthandler`` is given
|
||||
on the command-line.
|
||||
|
||||
Also the :confval:`faulthandler_timeout=X<faulthandler_timeout>` configuration option can be used
|
||||
to dump the traceback of all threads if a test takes longer than ``X``
|
||||
seconds to finish (not available on Windows).
|
||||
|
||||
.. note::
|
||||
|
||||
This functionality has been integrated from the external
|
||||
`pytest-faulthandler <https://github.com/pytest-dev/pytest-faulthandler>`__ plugin, with two
|
||||
small differences:
|
||||
|
||||
* To disable it, use ``-p no:faulthandler`` instead of ``--no-faulthandler``: the former
|
||||
can be used with any plugin, so it saves one option.
|
||||
|
||||
* The ``--faulthandler-timeout`` command-line option has become the
|
||||
:confval:`faulthandler_timeout` configuration option. It can still be configured from
|
||||
the command-line using ``-o faulthandler_timeout=X``.
|
||||
|
||||
|
||||
.. _unraisable:
|
||||
|
||||
Warning about unraisable exceptions and unhandled thread exceptions
|
||||
-------------------------------------------------------------------
|
||||
|
||||
.. versionadded:: 6.2
|
||||
|
||||
.. note::
|
||||
|
||||
These features only work on Python>=3.8.
|
||||
|
||||
Unhandled exceptions are exceptions that are raised in a situation in which
|
||||
they cannot propagate to a caller. The most common case is an exception raised
|
||||
in a :meth:`__del__ <object.__del__>` implementation.
|
||||
|
||||
Unhandled thread exceptions are exceptions raised in a :class:`~threading.Thread`
|
||||
but not handled, causing the thread to terminate uncleanly.
|
||||
|
||||
Both types of exceptions are normally considered bugs, but may go unnoticed
|
||||
because they don't cause the program itself to crash. Pytest detects these
|
||||
conditions and issues a warning that is visible in the test run summary.
|
||||
|
||||
The plugins are automatically enabled for pytest runs, unless the
|
||||
``-p no:unraisableexception`` (for unraisable exceptions) and
|
||||
``-p no:threadexception`` (for thread exceptions) options are given on the
|
||||
command-line.
|
||||
|
||||
The warnings may be silenced selectivly using the :ref:`pytest.mark.filterwarnings ref`
|
||||
mark. The warning categories are :class:`pytest.PytestUnraisableExceptionWarning` and
|
||||
:class:`pytest.PytestUnhandledThreadExceptionWarning`.
|
||||
.. _`PyPy-test`: http://buildbot.pypy.org/summary
|
||||
|
||||
|
||||
Creating JUnitXML format files
|
||||
@@ -540,7 +511,7 @@ instead, configure the ``junit_duration_report`` option like this:
|
||||
.. _record_property example:
|
||||
|
||||
record_property
|
||||
^^^^^^^^^^^^^^^
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to log additional information for a test, you can use the
|
||||
``record_property`` fixture:
|
||||
@@ -602,10 +573,9 @@ Will result in:
|
||||
Please note that using this feature will break schema verifications for the latest JUnitXML schema.
|
||||
This might be a problem when used with some CI servers.
|
||||
|
||||
|
||||
record_xml_attribute
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To add an additional xml attribute to a testcase element, you can use
|
||||
``record_xml_attribute`` fixture. This can also be used to override existing values:
|
||||
@@ -714,34 +684,8 @@ The generated XML is compatible with the latest ``xunit`` standard, contrary to
|
||||
and `record_xml_attribute`_.
|
||||
|
||||
|
||||
Creating resultlog format files
|
||||
----------------------------------------------------
|
||||
|
||||
|
||||
To create plain-text machine-readable result files you can issue:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --resultlog=path
|
||||
|
||||
and look at the content at the ``path`` location. Such files are used e.g.
|
||||
by the `PyPy-test`_ web page to show test results over several revisions.
|
||||
|
||||
.. warning::
|
||||
|
||||
This option is rarely used and is scheduled for removal in pytest 6.0.
|
||||
|
||||
If you use this option, consider using the new `pytest-reportlog <https://github.com/pytest-dev/pytest-reportlog>`__ plugin instead.
|
||||
|
||||
See `the deprecation docs <https://docs.pytest.org/en/stable/deprecations.html#result-log-result-log>`__
|
||||
for more information.
|
||||
|
||||
|
||||
.. _`PyPy-test`: http://buildbot.pypy.org/summary
|
||||
|
||||
|
||||
Sending test report to online pastebin service
|
||||
-----------------------------------------------------
|
||||
Sending test report to an online pastebin service
|
||||
--------------------------------------------------
|
||||
|
||||
**Creating a URL for each test failure**:
|
||||
|
||||
@@ -759,114 +703,11 @@ for example ``-x`` if you only want to send one particular failure.
|
||||
|
||||
pytest --pastebin=all
|
||||
|
||||
Currently only pasting to the http://bpaste.net service is implemented.
|
||||
Currently only pasting to the https://bpaste.net/ service is implemented.
|
||||
|
||||
.. versionchanged:: 5.2
|
||||
|
||||
If creating the URL fails for any reason, a warning is generated instead of failing the
|
||||
entire test suite.
|
||||
|
||||
Early loading plugins
|
||||
---------------------
|
||||
|
||||
You can early-load plugins (internal and external) explicitly in the command-line with the ``-p`` option::
|
||||
|
||||
pytest -p mypluginmodule
|
||||
|
||||
The option receives a ``name`` parameter, which can be:
|
||||
|
||||
* A full module dotted name, for example ``myproject.plugins``. This dotted name must be importable.
|
||||
* The entry-point name of a plugin. This is the name passed to ``setuptools`` when the plugin is
|
||||
registered. For example to early-load the `pytest-cov <https://pypi.org/project/pytest-cov/>`__ plugin you can use::
|
||||
|
||||
pytest -p pytest_cov
|
||||
|
||||
|
||||
Disabling plugins
|
||||
-----------------
|
||||
|
||||
To disable loading specific plugins at invocation time, use the ``-p`` option
|
||||
together with the prefix ``no:``.
|
||||
|
||||
Example: to disable loading the plugin ``doctest``, which is responsible for
|
||||
executing doctest tests from text files, invoke pytest like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -p no:doctest
|
||||
|
||||
.. _`pytest.main-usage`:
|
||||
|
||||
Calling pytest from Python code
|
||||
----------------------------------------------------
|
||||
|
||||
|
||||
|
||||
You can invoke ``pytest`` from Python code directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pytest.main()
|
||||
|
||||
this acts as if you would call "pytest" from the command line.
|
||||
It will not raise ``SystemExit`` but return the exitcode instead.
|
||||
You can pass in options and arguments:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pytest.main(["-x", "mytestdir"])
|
||||
|
||||
You can specify additional plugins to ``pytest.main``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of myinvoke.py
|
||||
import pytest
|
||||
|
||||
|
||||
class MyPlugin:
|
||||
def pytest_sessionfinish(self):
|
||||
print("*** test run reporting finishing")
|
||||
|
||||
|
||||
pytest.main(["-qq"], plugins=[MyPlugin()])
|
||||
|
||||
Running it will show that ``MyPlugin`` was added and its
|
||||
hook was invoked:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ python myinvoke.py
|
||||
.FEsxX. [100%]*** test run reporting finishing
|
||||
|
||||
================================== ERRORS ==================================
|
||||
_______________________ ERROR at setup of test_error _______________________
|
||||
|
||||
@pytest.fixture
|
||||
def error_fixture():
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_example.py:6: AssertionError
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_fail _________________________________
|
||||
|
||||
def test_fail():
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_example.py:14: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_example.py::test_fail - assert 0
|
||||
ERROR test_example.py::test_error - assert 0
|
||||
|
||||
.. note::
|
||||
|
||||
Calling ``pytest.main()`` will result in importing your tests and any modules
|
||||
that they import. Due to the caching mechanism of python's import system,
|
||||
making subsequent calls to ``pytest.main()`` from the same process will not
|
||||
reflect changes to those files between the calls. For this reason, making
|
||||
multiple calls to ``pytest.main()`` from the same process (in order to re-run
|
||||
tests, for example) is not recommended.
|
||||
|
||||
.. _jenkins: http://jenkins-ci.org/
|
||||
.. _jenkins: https://jenkins-ci.org
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
.. _`parametrize-basics`:
|
||||
|
||||
Parametrizing fixtures and test functions
|
||||
How to parametrize fixtures and test functions
|
||||
==========================================================================
|
||||
|
||||
pytest enables test parametrization at several levels:
|
||||
@@ -2,8 +2,8 @@
|
||||
.. _`extplugins`:
|
||||
.. _`using plugins`:
|
||||
|
||||
Installing and Using plugins
|
||||
============================
|
||||
How to install and use plugins
|
||||
===============================
|
||||
|
||||
This section talks about installing and using third party plugins.
|
||||
For writing your own plugins, please refer to :ref:`writing-plugins`.
|
||||
@@ -26,7 +26,7 @@ Here is a little annotated list for some popular plugins:
|
||||
for `django`_ apps, using pytest integration.
|
||||
|
||||
* `pytest-twisted <https://pypi.org/project/pytest-twisted/>`_: write tests
|
||||
for `twisted <http://twistedmatrix.com>`_ apps, starting a reactor and
|
||||
for `twisted <https://twistedmatrix.com/>`_ apps, starting a reactor and
|
||||
processing deferreds from test functions.
|
||||
|
||||
* `pytest-cov <https://pypi.org/project/pytest-cov/>`__:
|
||||
@@ -58,7 +58,7 @@ Here is a little annotated list for some popular plugins:
|
||||
|
||||
To see a complete list of all plugins with their latest testing
|
||||
status against different pytest and Python versions, please visit
|
||||
`plugincompat <http://plugincompat.herokuapp.com/>`_.
|
||||
:ref:`plugin-list`.
|
||||
|
||||
You may also discover more plugins through a `pytest- pypi.org search`_.
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
.. _skipping:
|
||||
|
||||
Skip and xfail: dealing with tests that cannot succeed
|
||||
======================================================
|
||||
How to use skip and xfail to deal with tests that cannot succeed
|
||||
=================================================================
|
||||
|
||||
You can mark test functions that cannot be run on certain platforms
|
||||
or that you expect to fail so pytest can deal with them accordingly and
|
||||
@@ -365,13 +365,16 @@ Examples
|
||||
|
||||
Here is a simple test file with the several usages:
|
||||
|
||||
.. literalinclude:: example/xfail_demo.py
|
||||
.. literalinclude:: /example/xfail_demo.py
|
||||
|
||||
Running it with the report-on-xfail option gives this output:
|
||||
|
||||
.. FIXME: Use $ instead of ! again to reenable regendoc once it's fixed:
|
||||
https://github.com/pytest-dev/pytest/issues/8807
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
example $ pytest -rx xfail_demo.py
|
||||
! pytest -rx xfail_demo.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
@@ -405,6 +408,7 @@ test instances when using parametrize:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -2,20 +2,17 @@
|
||||
.. _`tmpdir handling`:
|
||||
.. _tmpdir:
|
||||
|
||||
Temporary directories and files
|
||||
================================================
|
||||
How to use temporary directories and files in tests
|
||||
===================================================
|
||||
|
||||
The ``tmp_path`` fixture
|
||||
------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
You can use the ``tmp_path`` fixture which will
|
||||
provide a temporary directory unique to the test invocation,
|
||||
created in the `base temporary directory`_.
|
||||
|
||||
``tmp_path`` is a ``pathlib.Path`` object. Here is an example test usage:
|
||||
``tmp_path`` is a :class:`pathlib.Path` object. Here is an example test usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -71,82 +68,12 @@ Running this would result in a passed test except for the last
|
||||
The ``tmp_path_factory`` fixture
|
||||
--------------------------------
|
||||
|
||||
|
||||
|
||||
|
||||
The ``tmp_path_factory`` is a session-scoped fixture which can be used
|
||||
to create arbitrary temporary directories from any other fixture or test.
|
||||
|
||||
It is intended to replace ``tmpdir_factory``, and returns :class:`pathlib.Path` instances.
|
||||
|
||||
See :ref:`tmp_path_factory API <tmp_path_factory factory api>` for details.
|
||||
|
||||
|
||||
The 'tmpdir' fixture
|
||||
--------------------
|
||||
|
||||
You can use the ``tmpdir`` fixture which will
|
||||
provide a temporary directory unique to the test invocation,
|
||||
created in the `base temporary directory`_.
|
||||
|
||||
``tmpdir`` is a `py.path.local`_ object which offers ``os.path`` methods
|
||||
and more. Here is an example test usage:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_tmpdir.py
|
||||
def test_create_file(tmpdir):
|
||||
p = tmpdir.mkdir("sub").join("hello.txt")
|
||||
p.write("content")
|
||||
assert p.read() == "content"
|
||||
assert len(tmpdir.listdir()) == 1
|
||||
assert 0
|
||||
|
||||
Running this would result in a passed test except for the last
|
||||
``assert 0`` line which we use to look at values:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest test_tmpdir.py
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-6.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_tmpdir.py F [100%]
|
||||
|
||||
================================= FAILURES =================================
|
||||
_____________________________ test_create_file _____________________________
|
||||
|
||||
tmpdir = local('PYTEST_TMPDIR/test_create_file0')
|
||||
|
||||
def test_create_file(tmpdir):
|
||||
p = tmpdir.mkdir("sub").join("hello.txt")
|
||||
p.write("content")
|
||||
assert p.read() == "content"
|
||||
assert len(tmpdir.listdir()) == 1
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_tmpdir.py:6: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_tmpdir.py::test_create_file - assert 0
|
||||
============================ 1 failed in 0.12s =============================
|
||||
|
||||
.. _`tmpdir factory example`:
|
||||
|
||||
The 'tmpdir_factory' fixture
|
||||
----------------------------
|
||||
|
||||
|
||||
|
||||
The ``tmpdir_factory`` is a session-scoped fixture which can be used
|
||||
to create arbitrary temporary directories from any other fixture or test.
|
||||
|
||||
For example, suppose your test suite needs a large image on disk, which is
|
||||
generated procedurally. Instead of computing the same image for each test
|
||||
that uses it into its own ``tmpdir``, you can generate it once per-session
|
||||
that uses it into its own ``tmp_path``, you can generate it once per-session
|
||||
to save time:
|
||||
|
||||
.. code-block:: python
|
||||
@@ -156,10 +83,10 @@ to save time:
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def image_file(tmpdir_factory):
|
||||
def image_file(tmp_path_factory):
|
||||
img = compute_expensive_image()
|
||||
fn = tmpdir_factory.mktemp("data").join("img.png")
|
||||
img.save(str(fn))
|
||||
fn = tmp_path_factory.mktemp("data") / "img.png"
|
||||
img.save(fn)
|
||||
return fn
|
||||
|
||||
|
||||
@@ -168,7 +95,20 @@ to save time:
|
||||
img = load_image(image_file)
|
||||
# compute and test histogram
|
||||
|
||||
See :ref:`tmpdir_factory API <tmpdir factory api>` for details.
|
||||
See :ref:`tmp_path_factory API <tmp_path_factory factory api>` for details.
|
||||
|
||||
.. _`tmpdir and tmpdir_factory`:
|
||||
|
||||
The ``tmpdir`` and ``tmpdir_factory`` fixtures
|
||||
---------------------------------------------------
|
||||
|
||||
The ``tmpdir`` and ``tmpdir_factory`` fixtures are similar to ``tmp_path``
|
||||
and ``tmp_path_factory``, but use/return legacy `py.path.local`_ objects
|
||||
rather than standard :class:`pathlib.Path` objects. These days, prefer to
|
||||
use ``tmp_path`` and ``tmp_path_factory``.
|
||||
|
||||
See :fixture:`tmpdir <tmpdir>` :fixture:`tmpdir_factory <tmpdir_factory>`
|
||||
API for details.
|
||||
|
||||
|
||||
.. _`base temporary directory`:
|
||||
@@ -2,8 +2,8 @@
|
||||
.. _`unittest.TestCase`:
|
||||
.. _`unittest`:
|
||||
|
||||
unittest.TestCase Support
|
||||
=========================
|
||||
How to use ``unittest``-based tests with pytest
|
||||
===============================================
|
||||
|
||||
``pytest`` supports running Python ``unittest``-based tests out of the box.
|
||||
It's meant for leveraging existing ``unittest``-based test suites
|
||||
@@ -190,21 +190,22 @@ and define the fixture function in the context where you want it used.
|
||||
Let's look at an ``initdir`` fixture which makes all test methods of a
|
||||
``TestCase`` class execute in a temporary directory with a
|
||||
pre-initialized ``samplefile.ini``. Our ``initdir`` fixture itself uses
|
||||
the pytest builtin :ref:`tmpdir <tmpdir>` fixture to delegate the
|
||||
the pytest builtin :fixture:`tmp_path` fixture to delegate the
|
||||
creation of a per-test temporary directory:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_unittest_cleandir.py
|
||||
import os
|
||||
import pytest
|
||||
import unittest
|
||||
|
||||
|
||||
class MyTest(unittest.TestCase):
|
||||
@pytest.fixture(autouse=True)
|
||||
def initdir(self, tmpdir):
|
||||
tmpdir.chdir() # change to pytest-provided temporary directory
|
||||
tmpdir.join("samplefile.ini").write("# testdata")
|
||||
def initdir(self, tmp_path, monkeypatch):
|
||||
monkeypatch.chdir(tmp_path) # change to pytest-provided temporary directory
|
||||
tmp_path.joinpath("samplefile.ini").write_text("# testdata")
|
||||
|
||||
def test_method(self):
|
||||
with open("samplefile.ini") as f:
|
||||
233
doc/en/how-to/usage.rst
Normal file
233
doc/en/how-to/usage.rst
Normal file
@@ -0,0 +1,233 @@
|
||||
|
||||
.. _usage:
|
||||
|
||||
How to invoke pytest
|
||||
==========================================
|
||||
|
||||
.. seealso:: :ref:`Complete pytest command-line flag reference <command-line-flags>`
|
||||
|
||||
In general, pytest is invoked with the command ``pytest`` (see below for :ref:`other ways to invoke pytest
|
||||
<invoke-other>`). This will execute all tests in all files whose names follow the form ``test_*.py`` or ``\*_test.py``
|
||||
in the current directory and its subdirectories. More generally, pytest follows :ref:`standard test discovery rules
|
||||
<test discovery>`.
|
||||
|
||||
|
||||
.. _select-tests:
|
||||
|
||||
Specifying which tests to run
|
||||
------------------------------
|
||||
|
||||
Pytest supports several ways to run and select tests from the command-line.
|
||||
|
||||
**Run tests in a module**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py
|
||||
|
||||
**Run tests in a directory**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest testing/
|
||||
|
||||
**Run tests by keyword expressions**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -k "MyClass and not method"
|
||||
|
||||
This will run tests which contain names that match the given *string expression* (case-insensitive),
|
||||
which can include Python operators that use filenames, class names and function names as variables.
|
||||
The example above will run ``TestMyClass.test_something`` but not ``TestMyClass.test_method_simple``.
|
||||
|
||||
.. _nodeids:
|
||||
|
||||
**Run tests by node ids**
|
||||
|
||||
Each collected test is assigned a unique ``nodeid`` which consist of the module filename followed
|
||||
by specifiers like class names, function names and parameters from parametrization, separated by ``::`` characters.
|
||||
|
||||
To run a specific test within a module:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py::test_func
|
||||
|
||||
|
||||
Another example specifying a test method in the command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest test_mod.py::TestClass::test_method
|
||||
|
||||
**Run tests by marker expressions**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -m slow
|
||||
|
||||
Will run all tests which are decorated with the ``@pytest.mark.slow`` decorator.
|
||||
|
||||
For more information see :ref:`marks <mark>`.
|
||||
|
||||
**Run tests from packages**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pyargs pkg.testing
|
||||
|
||||
This will import ``pkg.testing`` and use its filesystem location to find and run tests from.
|
||||
|
||||
|
||||
Getting help on version, option names, environment variables
|
||||
--------------------------------------------------------------
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --version # shows where pytest was imported from
|
||||
pytest --fixtures # show available builtin function arguments
|
||||
pytest -h | --help # show help on command line and config file options
|
||||
|
||||
|
||||
.. _durations:
|
||||
|
||||
Profiling test execution duration
|
||||
-------------------------------------
|
||||
|
||||
.. versionchanged:: 6.0
|
||||
|
||||
To get a list of the slowest 10 test durations over 1.0s long:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --durations=10 --durations-min=1.0
|
||||
|
||||
By default, pytest will not show test durations that are too small (<0.005s) unless ``-vv`` is passed on the command-line.
|
||||
|
||||
|
||||
Managing loading of plugins
|
||||
-------------------------------
|
||||
|
||||
Early loading plugins
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can early-load plugins (internal and external) explicitly in the command-line with the ``-p`` option::
|
||||
|
||||
pytest -p mypluginmodule
|
||||
|
||||
The option receives a ``name`` parameter, which can be:
|
||||
|
||||
* A full module dotted name, for example ``myproject.plugins``. This dotted name must be importable.
|
||||
* The entry-point name of a plugin. This is the name passed to ``setuptools`` when the plugin is
|
||||
registered. For example to early-load the `pytest-cov <https://pypi.org/project/pytest-cov/>`__ plugin you can use::
|
||||
|
||||
pytest -p pytest_cov
|
||||
|
||||
|
||||
Disabling plugins
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To disable loading specific plugins at invocation time, use the ``-p`` option
|
||||
together with the prefix ``no:``.
|
||||
|
||||
Example: to disable loading the plugin ``doctest``, which is responsible for
|
||||
executing doctest tests from text files, invoke pytest like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -p no:doctest
|
||||
|
||||
|
||||
.. _invoke-other:
|
||||
|
||||
Other ways of calling pytest
|
||||
-----------------------------------------------------
|
||||
|
||||
.. _invoke-python:
|
||||
|
||||
Calling pytest through ``python -m pytest``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can invoke testing through the Python interpreter from the command line:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
python -m pytest [...]
|
||||
|
||||
This is almost equivalent to invoking the command line script ``pytest [...]``
|
||||
directly, except that calling via ``python`` will also add the current directory to ``sys.path``.
|
||||
|
||||
|
||||
.. _`pytest.main-usage`:
|
||||
|
||||
Calling pytest from Python code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can invoke ``pytest`` from Python code directly:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
retcode = pytest.main()
|
||||
|
||||
this acts as if you would call "pytest" from the command line.
|
||||
It will not raise :class:`SystemExit` but return the :ref:`exit code <exit-codes>` instead.
|
||||
You can pass in options and arguments:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
retcode = pytest.main(["-x", "mytestdir"])
|
||||
|
||||
You can specify additional plugins to ``pytest.main``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of myinvoke.py
|
||||
import pytest
|
||||
|
||||
|
||||
class MyPlugin:
|
||||
def pytest_sessionfinish(self):
|
||||
print("*** test run reporting finishing")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main(["-qq"], plugins=[MyPlugin()]))
|
||||
|
||||
Running it will show that ``MyPlugin`` was added and its
|
||||
hook was invoked:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ python myinvoke.py
|
||||
.FEsxX. [100%]*** test run reporting finishing
|
||||
|
||||
================================== ERRORS ==================================
|
||||
_______________________ ERROR at setup of test_error _______________________
|
||||
|
||||
@pytest.fixture
|
||||
def error_fixture():
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_example.py:6: AssertionError
|
||||
================================= FAILURES =================================
|
||||
________________________________ test_fail _________________________________
|
||||
|
||||
def test_fail():
|
||||
> assert 0
|
||||
E assert 0
|
||||
|
||||
test_example.py:14: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_example.py::test_fail - assert 0
|
||||
ERROR test_example.py::test_error - assert 0
|
||||
|
||||
.. note::
|
||||
|
||||
Calling ``pytest.main()`` will result in importing your tests and any modules
|
||||
that they import. Due to the caching mechanism of python's import system,
|
||||
making subsequent calls to ``pytest.main()`` from the same process will not
|
||||
reflect changes to those files between the calls. For this reason, making
|
||||
multiple calls to ``pytest.main()`` from the same process (in order to re-run
|
||||
tests, for example) is not recommended.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user