Compare commits
733 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70f0b77c72 | ||
|
|
2a8b463b38 | ||
|
|
12bf458719 | ||
|
|
114dba56f8 | ||
|
|
abb853f482 | ||
|
|
8208a376cc | ||
|
|
f078984c2e | ||
|
|
dba62f8a46 | ||
|
|
f7bf914108 | ||
|
|
917195ea8e | ||
|
|
e7cd00ac92 | ||
|
|
693c3b7f61 | ||
|
|
fb3ae5eaa9 | ||
|
|
c8d23c206b | ||
|
|
c5de8e8c50 | ||
|
|
f360147758 | ||
|
|
65bd1b8a93 | ||
|
|
882f3a4cd7 | ||
|
|
56e430f74e | ||
|
|
654d8da9f7 | ||
|
|
ace3a02cd4 | ||
|
|
f013a5e8c1 | ||
|
|
fbd8ff9502 | ||
|
|
737a1bf947 | ||
|
|
843ca03770 | ||
|
|
5cbc06a453 | ||
|
|
da23aa3419 | ||
|
|
28bf3816e7 | ||
|
|
d6ce2e5858 | ||
|
|
5ac498ea96 | ||
|
|
6765aca0d1 | ||
|
|
72fc43952b | ||
|
|
6896dbc5ca | ||
|
|
49c6aebbc7 | ||
|
|
fb12d2a612 | ||
|
|
8e51563384 | ||
|
|
61dfd0a94f | ||
|
|
f9cafd1c94 | ||
|
|
b10f28949d | ||
|
|
b0f090890c | ||
|
|
f0a4a13e48 | ||
|
|
ff80464b47 | ||
|
|
480dd9e6d6 | ||
|
|
ceb4f3f701 | ||
|
|
ea3ebec117 | ||
|
|
bf3b26b3f7 | ||
|
|
84569ca4da | ||
|
|
af21e6b45c | ||
|
|
5c5966f62d | ||
|
|
31b1c4ca0c | ||
|
|
61b76c7f5f | ||
|
|
c35544a0f7 | ||
|
|
5bc3ad8e27 | ||
|
|
a930ca0b45 | ||
|
|
d4b85da8c7 | ||
|
|
0025e4408f | ||
|
|
81cc73103a | ||
|
|
97d8e9fbec | ||
|
|
220a2a1bc9 | ||
|
|
2e2e895b4b | ||
|
|
bce45052a6 | ||
|
|
2f48ae4e66 | ||
|
|
6061ecf95a | ||
|
|
e032904413 | ||
|
|
ece774f0eb | ||
|
|
bc49d6ff99 | ||
|
|
2b9ca34280 | ||
|
|
e38561037d | ||
|
|
0a57124063 | ||
|
|
13f02af97d | ||
|
|
f2ed796c41 | ||
|
|
b3f8fabac8 | ||
|
|
22d91a3c3a | ||
|
|
322a0f0a33 | ||
|
|
58149459a5 | ||
|
|
852fb6a4ae | ||
|
|
437d6452c1 | ||
|
|
e37ff3042e | ||
|
|
ecd2de25a1 | ||
|
|
c607697400 | ||
|
|
0996f3dbc5 | ||
|
|
a0dbf2ab99 | ||
|
|
ddbe733666 | ||
|
|
470e686a70 | ||
|
|
765f75a8f1 | ||
|
|
6b5152ae13 | ||
|
|
10ca84ffc5 | ||
|
|
e393a73890 | ||
|
|
bed3918cbc | ||
|
|
31dfbb4668 | ||
|
|
b4d75ad31d | ||
|
|
ec6d0fa4d7 | ||
|
|
fa8a658458 | ||
|
|
66f20b6f5e | ||
|
|
6ba5e3c071 | ||
|
|
b900b4155f | ||
|
|
364ae5d723 | ||
|
|
84c7fef836 | ||
|
|
aaea4e52ef | ||
|
|
0cacdadc97 | ||
|
|
6c56070df1 | ||
|
|
f9f41e69a8 | ||
|
|
b2ce6f3200 | ||
|
|
e0b584d048 | ||
|
|
a0ff5deabf | ||
|
|
97b85a17ae | ||
|
|
de7ba5958b | ||
|
|
8a498700da | ||
|
|
45c894b73f | ||
|
|
65342db7a4 | ||
|
|
d391274f39 | ||
|
|
c5fa1d1c3e | ||
|
|
a304dbb519 | ||
|
|
d19df5efa2 | ||
|
|
6663cb054c | ||
|
|
b27e40cbf1 | ||
|
|
ee52a8a5f8 | ||
|
|
8f04bd003c | ||
|
|
93fd9debe3 | ||
|
|
ff428bfee1 | ||
|
|
0f7c7a99bf | ||
|
|
041ea3704b | ||
|
|
d94b4b031f | ||
|
|
e253029ad0 | ||
|
|
43617a8c47 | ||
|
|
56bf7446f6 | ||
|
|
8e42c5b7db | ||
|
|
0571e1ee8e | ||
|
|
b0a6161d41 | ||
|
|
06fa2bc0b8 | ||
|
|
8abd4aec6e | ||
|
|
858010e214 | ||
|
|
96424272a1 | ||
|
|
e44a2ef653 | ||
|
|
c6e3ff3ce5 | ||
|
|
a31098a74e | ||
|
|
7e8044f9b8 | ||
|
|
b81173ea0c | ||
|
|
c8f7e50c47 | ||
|
|
c0e53a61e6 | ||
|
|
494ac28a32 | ||
|
|
dc75b6af47 | ||
|
|
7573747cda | ||
|
|
2db05b6582 | ||
|
|
4318698bae | ||
|
|
e668aaf885 | ||
|
|
58e6a09db4 | ||
|
|
6718a2f028 | ||
|
|
c081c01eb1 | ||
|
|
f8e1d58e8f | ||
|
|
18024467ff | ||
|
|
2ad36b1402 | ||
|
|
6ca3e1e425 | ||
|
|
ecd072ea94 | ||
|
|
dda21935a7 | ||
|
|
cc464f6b96 | ||
|
|
6a43c8cd94 | ||
|
|
63fe547d9f | ||
|
|
b709e61892 | ||
|
|
465b2d998a | ||
|
|
184ef92f0b | ||
|
|
73bbff2b74 | ||
|
|
4ccaa987d4 | ||
|
|
3a4a815c41 | ||
|
|
dae455e8a3 | ||
|
|
0594dba5ce | ||
|
|
f1183c2422 | ||
|
|
685ca96c71 | ||
|
|
ccf6c3cb46 | ||
|
|
ceca35b94a | ||
|
|
803d68847b | ||
|
|
0bd02cd1bc | ||
|
|
0b8b006db4 | ||
|
|
73b74c74c9 | ||
|
|
4d782dc13f | ||
|
|
e1756fc631 | ||
|
|
5d7686951c | ||
|
|
80c5f6e609 | ||
|
|
0b47e51d08 | ||
|
|
5eeb5ee960 | ||
|
|
ed2b715f4c | ||
|
|
7e08e09473 | ||
|
|
3ac43314ee | ||
|
|
972410f8b6 | ||
|
|
0cf267f187 | ||
|
|
7161f5b372 | ||
|
|
2051e30b9b | ||
|
|
f339147d12 | ||
|
|
c04767f946 | ||
|
|
6d040370ed | ||
|
|
1d466d0aa7 | ||
|
|
ef4dec0bcf | ||
|
|
d76735f9e5 | ||
|
|
d1a48ad68f | ||
|
|
6d259c400e | ||
|
|
d3686361ba | ||
|
|
8605ed2a15 | ||
|
|
8b34d981fc | ||
|
|
2795689435 | ||
|
|
dcf65a9643 | ||
|
|
784e1e3b7e | ||
|
|
4a2fdce62b | ||
|
|
32a5e80a6d | ||
|
|
0e8a8f94f6 | ||
|
|
8f23e19bcb | ||
|
|
f5c1f3df71 | ||
|
|
b25802eca7 | ||
|
|
7f7f84757d | ||
|
|
143499d041 | ||
|
|
26b41a5914 | ||
|
|
9f66102869 | ||
|
|
e1a426c067 | ||
|
|
2bd97ebaf7 | ||
|
|
45eeb53c98 | ||
|
|
254b195f50 | ||
|
|
865e84d206 | ||
|
|
1c13418a8b | ||
|
|
299e6479c1 | ||
|
|
6e81c3df92 | ||
|
|
1bd7d287a7 | ||
|
|
b82e1b87cc | ||
|
|
af40473c9a | ||
|
|
f17b734989 | ||
|
|
f050203f5d | ||
|
|
3f5622c577 | ||
|
|
1fb3f63f35 | ||
|
|
fc2ad1dbed | ||
|
|
bc6450773a | ||
|
|
204004c8b8 | ||
|
|
772a4a5cf3 | ||
|
|
fb6dad60a0 | ||
|
|
d9cad1e759 | ||
|
|
02053bf556 | ||
|
|
6fb3baf071 | ||
|
|
ff5317a7f3 | ||
|
|
766fc23151 | ||
|
|
08734bdd18 | ||
|
|
e943aff995 | ||
|
|
9c5da9c0d1 | ||
|
|
f6ab6d71ad | ||
|
|
67755d67fb | ||
|
|
a3c2ec3c5b | ||
|
|
9742f11d37 | ||
|
|
915ecb0dac | ||
|
|
53cd7fd2ea | ||
|
|
8532e991a5 | ||
|
|
50937fe622 | ||
|
|
ebc0cea226 | ||
|
|
65133018f3 | ||
|
|
ac7ee40aaf | ||
|
|
308b733b9d | ||
|
|
76c6ed8b05 | ||
|
|
7f519f8ab7 | ||
|
|
9c700d1fd5 | ||
|
|
19cd4d0af7 | ||
|
|
bf0fe1a1fa | ||
|
|
3df32e2732 | ||
|
|
0bf363472e | ||
|
|
34bc594beb | ||
|
|
bc00d0f7db | ||
|
|
e3e57a755b | ||
|
|
79d5fc3a0b | ||
|
|
322d686ab4 | ||
|
|
f75f7c1925 | ||
|
|
698c4e75fd | ||
|
|
4749dca764 | ||
|
|
649d23c8a8 | ||
|
|
e87d3d70e2 | ||
|
|
1460ad6027 | ||
|
|
78cd1a07d0 | ||
|
|
d67d68f6d3 | ||
|
|
008d04398a | ||
|
|
c3178a176d | ||
|
|
df1d1105b0 | ||
|
|
2b11b2c093 | ||
|
|
adb8edbae1 | ||
|
|
0e651d7297 | ||
|
|
3cff5e252d | ||
|
|
7412df0920 | ||
|
|
990133f804 | ||
|
|
df68808d29 | ||
|
|
b64d9402ca | ||
|
|
8d3a5dcd1b | ||
|
|
9eac4733c5 | ||
|
|
24bd51bda0 | ||
|
|
9374114370 | ||
|
|
eb13530560 | ||
|
|
5530d3e15d | ||
|
|
ea79eb5c3f | ||
|
|
c8b904a406 | ||
|
|
d45fa7b212 | ||
|
|
852ca7ad59 | ||
|
|
006dc30476 | ||
|
|
45ba736c81 | ||
|
|
c453fe7053 | ||
|
|
cc005af47e | ||
|
|
20c624efcf | ||
|
|
b2be6c1a30 | ||
|
|
c43a9c83ee | ||
|
|
e804e419bc | ||
|
|
992e7f7771 | ||
|
|
bd1a2e6435 | ||
|
|
1d137fd2fe | ||
|
|
f1f1862b19 | ||
|
|
6f0a5789fb | ||
|
|
cc78a533ae | ||
|
|
fd0b3e2e8b | ||
|
|
f3dbe5a308 | ||
|
|
1da8ce65a6 | ||
|
|
1dd5f088fa | ||
|
|
6a73714b00 | ||
|
|
6371243c10 | ||
|
|
533e610a35 | ||
|
|
8fd5a658eb | ||
|
|
c3b7efc818 | ||
|
|
43e7401c91 | ||
|
|
a9e850f749 | ||
|
|
da2e092163 | ||
|
|
8449294e5d | ||
|
|
19035f4b55 | ||
|
|
48ed437e70 | ||
|
|
14d3d9187f | ||
|
|
a37d1df089 | ||
|
|
97cd5f0deb | ||
|
|
1dafe969d1 | ||
|
|
8b2fcf517c | ||
|
|
42e60d935a | ||
|
|
1f66e3b0d0 | ||
|
|
b3759372ad | ||
|
|
f5d2b199e2 | ||
|
|
bc157417e1 | ||
|
|
12133d4eb7 | ||
|
|
148f2fc72c | ||
|
|
5d9d12a6be | ||
|
|
dde27a2305 | ||
|
|
10fa66e5b5 | ||
|
|
5e26304d81 | ||
|
|
d0860a339b | ||
|
|
fcbfdef11b | ||
|
|
b84f826fc8 | ||
|
|
ec46864922 | ||
|
|
c36a90531a | ||
|
|
3fa329c9e9 | ||
|
|
a70e5f119e | ||
|
|
b6b7185b7b | ||
|
|
4fb7a91a5e | ||
|
|
ff5e98c654 | ||
|
|
2662c400ba | ||
|
|
d8d835c1f5 | ||
|
|
06029d11d3 | ||
|
|
4c0ba6017d | ||
|
|
c70ecd49ca | ||
|
|
50edab8004 | ||
|
|
b4b9f788af | ||
|
|
a7e49e6c07 | ||
|
|
2b1ae8a66d | ||
|
|
2ebb69b50a | ||
|
|
4fca86e2af | ||
|
|
9ad00714ba | ||
|
|
b549438423 | ||
|
|
377888140f | ||
|
|
df377b589f | ||
|
|
87ce586d29 | ||
|
|
f599172add | ||
|
|
e20b39d928 | ||
|
|
4f33f46a02 | ||
|
|
159704421e | ||
|
|
0f965e57a2 | ||
|
|
8011ff5bda | ||
|
|
899e74aa14 | ||
|
|
66f743c45a | ||
|
|
8ad99c5cab | ||
|
|
da3f836ee3 | ||
|
|
37ecca3ba9 | ||
|
|
3d0ecd03ed | ||
|
|
eb5b2e0db5 | ||
|
|
47d92a0d96 | ||
|
|
7f1bf44aa8 | ||
|
|
5fec793bc7 | ||
|
|
e04936fc29 | ||
|
|
13a9d876f7 | ||
|
|
77526f412c | ||
|
|
0d4636b056 | ||
|
|
a65edf6711 | ||
|
|
973301b675 | ||
|
|
757ada2fd2 | ||
|
|
e88aa957ae | ||
|
|
8907fedc79 | ||
|
|
befc8a3f10 | ||
|
|
5935fbaa7a | ||
|
|
e8eaebe595 | ||
|
|
cec2dd6a7c | ||
|
|
266bf2c007 | ||
|
|
1f5a61e4ef | ||
|
|
46df1d5fcf | ||
|
|
d91527599a | ||
|
|
1410d3dc9a | ||
|
|
7538aa7bb9 | ||
|
|
db34bf01b6 | ||
|
|
9434541090 | ||
|
|
cc90bcce4c | ||
|
|
15ea5cef46 | ||
|
|
32a8d503a2 | ||
|
|
8c734dfc2f | ||
|
|
08ded2927a | ||
|
|
1c9dcf1f39 | ||
|
|
cab4069f42 | ||
|
|
4f6c67658c | ||
|
|
cda9ce198a | ||
|
|
9121138a1b | ||
|
|
407d74be27 | ||
|
|
49d690d137 | ||
|
|
deade370b9 | ||
|
|
00810b9b2a | ||
|
|
bcc08ffe4d | ||
|
|
ba1fc02a9b | ||
|
|
38d687f7c7 | ||
|
|
4621638f07 | ||
|
|
8881b201aa | ||
|
|
278b289f37 | ||
|
|
e7ade066b6 | ||
|
|
dee520e310 | ||
|
|
adebfd0a84 | ||
|
|
4e931b258d | ||
|
|
4011021823 | ||
|
|
bfda2a0050 | ||
|
|
2812c087ec | ||
|
|
6b5cddc48a | ||
|
|
403f556928 | ||
|
|
d8ef86aadf | ||
|
|
a9fe1e159a | ||
|
|
65c8e8a09e | ||
|
|
46d9243eb0 | ||
|
|
63a01bdb33 | ||
|
|
d53209956b | ||
|
|
951213ee09 | ||
|
|
ae067df941 | ||
|
|
40718efacc | ||
|
|
d406786a8d | ||
|
|
0ac069da13 | ||
|
|
d17ea7a9c0 | ||
|
|
c92021fc4f | ||
|
|
50a5cebba8 | ||
|
|
6c602c2282 | ||
|
|
76c70cbf4c | ||
|
|
3d9e68ecfd | ||
|
|
8b0b7156d9 | ||
|
|
cf6e2ceafd | ||
|
|
69a55d334a | ||
|
|
241b7433cd | ||
|
|
057c97812b | ||
|
|
02188e399d | ||
|
|
aae02863db | ||
|
|
49f36bb028 | ||
|
|
52730f6330 | ||
|
|
538efef1ba | ||
|
|
9311d822c7 | ||
|
|
351529cb50 | ||
|
|
94a2e3dddc | ||
|
|
ee96214a8d | ||
|
|
e1ae469504 | ||
|
|
0d00be4f4f | ||
|
|
23146e7527 | ||
|
|
b18df936ea | ||
|
|
4148663706 | ||
|
|
3e1971eb16 | ||
|
|
bcdb86ee7e | ||
|
|
2d77018d1b | ||
|
|
ceef0af1ae | ||
|
|
e4eec3416a | ||
|
|
645774295f | ||
|
|
f2e0c740d3 | ||
|
|
d856f4e51f | ||
|
|
7b9a414524 | ||
|
|
0c63f99016 | ||
|
|
3bc9cbea63 | ||
|
|
6eff3069da | ||
|
|
58a14b6b99 | ||
|
|
b53bf44139 | ||
|
|
d8758443bd | ||
|
|
51f64c2920 | ||
|
|
cea42ff9e4 | ||
|
|
2df9d05981 | ||
|
|
4142c41ffc | ||
|
|
de44293d59 | ||
|
|
5efe6ab93c | ||
|
|
ce59f42ce1 | ||
|
|
7da7b9610c | ||
|
|
d44e42ec15 | ||
|
|
0ea1889265 | ||
|
|
6352cf2374 | ||
|
|
3127ec737b | ||
|
|
aa0b657e58 | ||
|
|
d0f3f26fff | ||
|
|
08f3b02dfc | ||
|
|
2d690b83bf | ||
|
|
0642da0145 | ||
|
|
afa985c135 | ||
|
|
fd64fa1863 | ||
|
|
56dc01ffe0 | ||
|
|
5df45f5b27 | ||
|
|
05d55b86df | ||
|
|
475119988c | ||
|
|
7a6bcc3639 | ||
|
|
8e125c9759 | ||
|
|
ade773390a | ||
|
|
5c26ba9cb1 | ||
|
|
5a544d4fac | ||
|
|
2e7d6a6202 | ||
|
|
ea7357bc58 | ||
|
|
b3319a6074 | ||
|
|
c9628c52d6 | ||
|
|
dcbdcc729b | ||
|
|
15d608867d | ||
|
|
ea2c6b8a88 | ||
|
|
0e6cf0ff28 | ||
|
|
553951c443 | ||
|
|
15ef168821 | ||
|
|
cc6e5ec345 | ||
|
|
77643122a8 | ||
|
|
832cef953b | ||
|
|
bcdbb6b677 | ||
|
|
543779fc43 | ||
|
|
2ade3d5c89 | ||
|
|
7939e5327c | ||
|
|
f7171034f9 | ||
|
|
c7c120fba6 | ||
|
|
415899d428 | ||
|
|
8dda5613ef | ||
|
|
714f2113bb | ||
|
|
a50b92ea67 | ||
|
|
da81c1e49a | ||
|
|
23ab43233e | ||
|
|
1a119a22d1 | ||
|
|
77c5191ad7 | ||
|
|
7395501d1d | ||
|
|
920bffbfbb | ||
|
|
751c061d9a | ||
|
|
a624b84097 | ||
|
|
c75dd10671 | ||
|
|
b696666f5a | ||
|
|
f4f6cb7532 | ||
|
|
1e3d5a0412 | ||
|
|
98981276a0 | ||
|
|
8c96b65082 | ||
|
|
c926999cfb | ||
|
|
519157cfcf | ||
|
|
5d14362a75 | ||
|
|
15fe8c6e90 | ||
|
|
c1e01c2992 | ||
|
|
5e27ea5528 | ||
|
|
33d4c96aa2 | ||
|
|
b3eb5d1eb7 | ||
|
|
2af0a023c9 | ||
|
|
5f52d5ee17 | ||
|
|
95701566f3 | ||
|
|
57be1d60dd | ||
|
|
62f96eea6b | ||
|
|
fa3cca51e1 | ||
|
|
d441fa66fe | ||
|
|
43aee15ba3 | ||
|
|
5c57d92978 | ||
|
|
7afe17740f | ||
|
|
158432217c | ||
|
|
437ff1c01a | ||
|
|
40072b9511 | ||
|
|
520af9d767 | ||
|
|
bdac9d3dd0 | ||
|
|
37158f5303 | ||
|
|
612c3784e5 | ||
|
|
951e07d71d | ||
|
|
36f774a8fb | ||
|
|
a2b921f890 | ||
|
|
bd70f5c148 | ||
|
|
134b957bf4 | ||
|
|
4d21dc4f2d | ||
|
|
74416525d2 | ||
|
|
44cb51010c | ||
|
|
90597226eb | ||
|
|
7fb5ad82d9 | ||
|
|
f4bcb44025 | ||
|
|
b7ae7a654b | ||
|
|
148e6a30c8 | ||
|
|
47bd1688ed | ||
|
|
6630d96253 | ||
|
|
d32ab6029f | ||
|
|
76c00d1c09 | ||
|
|
492cc4219c | ||
|
|
51bf7c3aef | ||
|
|
489c61a22d | ||
|
|
0f3d630634 | ||
|
|
a0f652c559 | ||
|
|
877b57ae9b | ||
|
|
dc7ae41f33 | ||
|
|
2d43f42769 | ||
|
|
03ef546706 | ||
|
|
de5aa3847e | ||
|
|
0f4905a259 | ||
|
|
936f725b81 | ||
|
|
c86d2daf81 | ||
|
|
a70c1ca100 | ||
|
|
4668ee03f6 | ||
|
|
236bada755 | ||
|
|
76687030f0 | ||
|
|
2b3d69da2b | ||
|
|
8481e438bd | ||
|
|
bd2c9bedcf | ||
|
|
2fe922608f | ||
|
|
07fa69335c | ||
|
|
ddb16a1ab1 | ||
|
|
2e871f35f3 | ||
|
|
fa94e3c1b2 | ||
|
|
c6eb3413f3 | ||
|
|
54c70bc02c | ||
|
|
83558a0ba3 | ||
|
|
23ea04f910 | ||
|
|
c334adc78f | ||
|
|
f3f6cb2093 | ||
|
|
c4aa57bc4c | ||
|
|
2970c1df24 | ||
|
|
35c85f0db9 | ||
|
|
0deb7b1696 | ||
|
|
53b8aa065c | ||
|
|
6a2d122a50 | ||
|
|
d97473e551 | ||
|
|
525639eaa0 | ||
|
|
7dceabfcb2 | ||
|
|
e1f97e41e3 | ||
|
|
2d2f6cd4fd | ||
|
|
44c940765b | ||
|
|
ed68fcf665 | ||
|
|
907e9495a2 | ||
|
|
dac164cc99 | ||
|
|
4290cacb86 | ||
|
|
db5cc35b44 | ||
|
|
90031edde8 | ||
|
|
a96907a9db | ||
|
|
f8160f7bc5 | ||
|
|
f0d7773ffa | ||
|
|
84555c89de | ||
|
|
f7a3e001f7 | ||
|
|
42561db1ae | ||
|
|
0d31e852b1 | ||
|
|
75e1fde668 | ||
|
|
9cb71af9e5 | ||
|
|
0dd4cb0f8f | ||
|
|
33db5e081d | ||
|
|
a51dc0c7ce | ||
|
|
276ffa81f6 | ||
|
|
50610311a7 | ||
|
|
c30ab1014e | ||
|
|
df8869cf1a | ||
|
|
8b447878dc | ||
|
|
9c590fa474 | ||
|
|
a868a9ac13 | ||
|
|
55b78ff780 | ||
|
|
ccab469a0c | ||
|
|
e711a6c275 | ||
|
|
c1e3128b3f | ||
|
|
05bb5ffb65 | ||
|
|
ee95d666f8 | ||
|
|
1e2810e07d | ||
|
|
fec656b3b1 | ||
|
|
31174f3f83 | ||
|
|
5a0f379289 | ||
|
|
0138e9cbb0 | ||
|
|
b5cf61312b | ||
|
|
16cbb3196c | ||
|
|
f1254c4461 | ||
|
|
cd9415baf2 | ||
|
|
6bd77c0abd | ||
|
|
fb7ee7f42c | ||
|
|
9dcd6f2a87 | ||
|
|
e3eb26f91a | ||
|
|
86070f0b7d | ||
|
|
3fbe100a02 | ||
|
|
ee62674322 | ||
|
|
a4192160ce | ||
|
|
4d9296c71f | ||
|
|
d5d190335c | ||
|
|
7428064f79 | ||
|
|
af706edd59 | ||
|
|
4eb40ef283 | ||
|
|
f85f36ed03 | ||
|
|
904f1ca1ce | ||
|
|
32b85e4ccc | ||
|
|
c7bbb2a788 | ||
|
|
29112d7e0b | ||
|
|
3fd2f43fb6 | ||
|
|
2cf1de3f2d | ||
|
|
d9bdf5cfca | ||
|
|
f494eefcae | ||
|
|
c9e69438b1 | ||
|
|
2e89812fad | ||
|
|
a0207274f4 | ||
|
|
759d7fde5d | ||
|
|
a0f5c4c8f5 | ||
|
|
2e210acd00 | ||
|
|
ede6387caa | ||
|
|
ff25b52110 | ||
|
|
dc8c27037a | ||
|
|
3e11bd0d6e | ||
|
|
6a4c7063fd | ||
|
|
15fe60aa25 | ||
|
|
1ec7f60484 | ||
|
|
63e7f8e340 | ||
|
|
1cf9c2e76f | ||
|
|
0ca1f6e0f4 | ||
|
|
a68f4fd2b9 | ||
|
|
5b35241470 | ||
|
|
b26b731498 | ||
|
|
da305966d2 | ||
|
|
4ee10d2266 | ||
|
|
e1aeb6915e | ||
|
|
e75915bb73 | ||
|
|
ba2a43266a | ||
|
|
cfaa8bbee8 | ||
|
|
6b661795cf | ||
|
|
fa65b71c98 | ||
|
|
da5dec83f6 | ||
|
|
2ef3cb2510 | ||
|
|
c8a87e48ab | ||
|
|
b9561e29ff | ||
|
|
bf6dcd64dc | ||
|
|
214c331236 | ||
|
|
9cb504ca9a | ||
|
|
f0a9f9042f | ||
|
|
eeac28f4ab | ||
|
|
5505826db9 | ||
|
|
6e1ee0802f | ||
|
|
5cf58a9ae9 | ||
|
|
799bcccd1b | ||
|
|
821b6ef2a6 |
15
.coveragerc
15
.coveragerc
@@ -1,9 +1,18 @@
|
||||
[run]
|
||||
source = pytest,_pytest,testing/
|
||||
include =
|
||||
src/*
|
||||
testing/*
|
||||
*/lib/python*/site-packages/_pytest/*
|
||||
*/lib/python*/site-packages/pytest.py
|
||||
*/pypy*/site-packages/_pytest/*
|
||||
*/pypy*/site-packages/pytest.py
|
||||
*\Lib\site-packages\_pytest\*
|
||||
*\Lib\site-packages\pytest.py
|
||||
parallel = 1
|
||||
branch = 1
|
||||
|
||||
[paths]
|
||||
source = src/
|
||||
.tox/*/lib/python*/site-packages/
|
||||
.tox\*\Lib\site-packages\
|
||||
*/lib/python*/site-packages/
|
||||
*/pypy*/site-packages/
|
||||
*\Lib\site-packages\
|
||||
|
||||
4
.github/FUNDING.yml
vendored
Normal file
4
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# info:
|
||||
# * https://help.github.com/en/articles/displaying-a-sponsor-button-in-your-repository
|
||||
# * https://tidelift.com/subscription/how-to-connect-tidelift-with-github
|
||||
tidelift: pypi/pytest
|
||||
10
.github/ISSUE_TEMPLATE.md
vendored
10
.github/ISSUE_TEMPLATE.md
vendored
@@ -1,8 +1,10 @@
|
||||
<!--
|
||||
Thanks for submitting an issue!
|
||||
|
||||
Here's a quick checklist in what to include:
|
||||
Here's a quick checklist for what to provide:
|
||||
-->
|
||||
|
||||
- [ ] Include a detailed description of the bug or suggestion
|
||||
- [ ] `pip list` of the virtual environment you are using
|
||||
- [ ] a detailed description of the bug or suggestion
|
||||
- [ ] output of `pip list` from the virtual environment you are using
|
||||
- [ ] pytest and operating system versions
|
||||
- [ ] Minimal example if possible
|
||||
- [ ] minimal example if possible
|
||||
|
||||
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
8
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,9 +1,10 @@
|
||||
<!--
|
||||
Thanks for submitting a PR, your contribution is really appreciated!
|
||||
|
||||
Here's a quick checklist that should be present in PRs (you can delete this text from the final description, this is
|
||||
just a guideline):
|
||||
Here is a quick checklist that should be present in PRs.
|
||||
(please delete this text from the final description, this is just a guideline)
|
||||
-->
|
||||
|
||||
- [ ] 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.
|
||||
- [ ] Target the `master` branch for bug fixes, documentation updates and trivial changes.
|
||||
- [ ] Target the `features` branch for new features and removals/deprecations.
|
||||
- [ ] Include documentation when adding new features.
|
||||
@@ -11,4 +12,5 @@ just a guideline):
|
||||
|
||||
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.
|
||||
- [ ] Add yourself to `AUTHORS` in alphabetical order;
|
||||
|
||||
@@ -1,43 +1,44 @@
|
||||
exclude: doc/en/example/py2py3/test_py2.py
|
||||
repos:
|
||||
- repo: https://github.com/ambv/black
|
||||
rev: 18.9b0
|
||||
- repo: https://github.com/python/black
|
||||
rev: 19.3b0
|
||||
hooks:
|
||||
- id: black
|
||||
args: [--safe, --quiet]
|
||||
language_version: python3
|
||||
- repo: https://github.com/asottile/blacken-docs
|
||||
rev: v0.3.0
|
||||
rev: v0.5.0
|
||||
hooks:
|
||||
- id: blacken-docs
|
||||
additional_dependencies: [black==18.9b0]
|
||||
additional_dependencies: [black==19.3b0]
|
||||
language_version: python3
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v2.1.0
|
||||
rev: v2.2.2
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: fix-encoding-pragma
|
||||
- id: check-yaml
|
||||
- id: debug-statements
|
||||
exclude: _pytest/debugging.py
|
||||
language_version: python3
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.7.0
|
||||
rev: 3.7.7
|
||||
hooks:
|
||||
- id: flake8
|
||||
language_version: python3
|
||||
- repo: https://github.com/asottile/reorder_python_imports
|
||||
rev: v1.3.5
|
||||
rev: v1.4.0
|
||||
hooks:
|
||||
- id: reorder-python-imports
|
||||
args: ['--application-directories=.:src']
|
||||
- repo: https://github.com/asottile/pyupgrade
|
||||
rev: v1.11.1
|
||||
rev: v1.15.0
|
||||
hooks:
|
||||
- id: pyupgrade
|
||||
args: [--keep-percent-format]
|
||||
- repo: https://github.com/pre-commit/pygrep-hooks
|
||||
rev: v1.2.0
|
||||
rev: v1.3.0
|
||||
hooks:
|
||||
- id: rst-backticks
|
||||
- repo: local
|
||||
@@ -45,7 +46,7 @@ repos:
|
||||
- id: rst
|
||||
name: rst
|
||||
entry: rst-lint --encoding utf-8
|
||||
files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst|changelog/.*)$
|
||||
files: ^(CHANGELOG.rst|HOWTORELEASE.rst|README.rst|TIDELIFT.rst|changelog/.*)$
|
||||
language: python
|
||||
additional_dependencies: [pygments, restructuredtext_lint]
|
||||
- id: changelogs-rst
|
||||
|
||||
142
.travis.yml
142
.travis.yml
@@ -6,55 +6,74 @@ stages:
|
||||
if: repo = pytest-dev/pytest AND tag IS NOT present
|
||||
- name: deploy
|
||||
if: repo = pytest-dev/pytest AND tag IS present
|
||||
python:
|
||||
- '3.7'
|
||||
install:
|
||||
- pip install --upgrade --pre tox
|
||||
env:
|
||||
matrix:
|
||||
- TOXENV=py27
|
||||
# Specialized factors for py27.
|
||||
- TOXENV=py27-nobyte
|
||||
- TOXENV=py27-xdist
|
||||
- TOXENV=py27-pluggymaster
|
||||
# Specialized factors for py37.
|
||||
- TOXENV=py37-pexpect,py37-trial,py37-numpy
|
||||
- TOXENV=py37-pluggymaster
|
||||
- TOXENV=py37-freeze PYTEST_NO_COVERAGE=1
|
||||
python: '3.7'
|
||||
cache: false
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: '3.8-dev'
|
||||
env: TOXENV=py38-xdist
|
||||
env:
|
||||
global:
|
||||
- PYTEST_ADDOPTS=-vv
|
||||
|
||||
install:
|
||||
- python -m pip install --upgrade --pre tox
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# OSX tests - first (in test stage), since they are the slower ones.
|
||||
- &test-macos
|
||||
os: osx
|
||||
osx_image: xcode10.1
|
||||
language: generic
|
||||
# Coverage for:
|
||||
# - py2 with symlink in test_cmdline_python_package_symlink.
|
||||
env: TOXENV=py27-xdist PYTEST_COVERAGE=1
|
||||
before_install:
|
||||
- python -V
|
||||
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 27
|
||||
- <<: *test-macos
|
||||
env: TOXENV=py37-pexpect,py37-xdist PYTEST_COVERAGE=1
|
||||
before_install:
|
||||
- which python3
|
||||
- python3 -V
|
||||
- ln -sfn "$(which python3)" /usr/local/bin/python
|
||||
- python -V
|
||||
- test $(python -c 'import sys; print("%d%d" % sys.version_info[0:2])') = 37
|
||||
|
||||
# Full run of latest (major) supported versions, without xdist.
|
||||
- env: TOXENV=py27
|
||||
python: '2.7'
|
||||
- env: TOXENV=py37
|
||||
python: '3.7'
|
||||
|
||||
# Coverage tracking is slow with pypy, skip it.
|
||||
- env: TOXENV=pypy PYTEST_NO_COVERAGE=1
|
||||
python: 'pypy-5.4'
|
||||
dist: trusty
|
||||
- env: TOXENV=pypy-xdist
|
||||
python: 'pypy'
|
||||
- env: TOXENV=pypy3-xdist
|
||||
python: 'pypy3'
|
||||
|
||||
- env: TOXENV=py34-xdist
|
||||
python: '3.4'
|
||||
- env: TOXENV=py35-xdist
|
||||
python: '3.5'
|
||||
- env: TOXENV=py36-xdist
|
||||
python: '3.6'
|
||||
- env: TOXENV=py37
|
||||
- &test-macos
|
||||
language: generic
|
||||
os: osx
|
||||
osx_image: xcode9.4
|
||||
sudo: required
|
||||
install:
|
||||
- python -m pip install --pre tox
|
||||
env: TOXENV=py27-xdist
|
||||
- <<: *test-macos
|
||||
env: TOXENV=py37-xdist
|
||||
before_install:
|
||||
- brew update
|
||||
- brew upgrade python
|
||||
- brew unlink python
|
||||
- brew link python
|
||||
|
||||
# Coverage for:
|
||||
# - pytester's LsofFdLeakChecker
|
||||
# - TestArgComplete (linux only)
|
||||
# - numpy
|
||||
# Empty PYTEST_ADDOPTS to run this non-verbose.
|
||||
- env: TOXENV=py37-lsof-numpy-xdist PYTEST_COVERAGE=1 PYTEST_ADDOPTS=
|
||||
|
||||
# Specialized factors for py27.
|
||||
- env: TOXENV=py27-nobyte-numpy-xdist
|
||||
python: '2.7'
|
||||
- env: TOXENV=py27-pluggymaster-xdist
|
||||
python: '2.7'
|
||||
|
||||
# Specialized factors for py37.
|
||||
# Coverage for:
|
||||
# - test_sys_breakpoint_interception (via pexpect).
|
||||
- env: TOXENV=py37-pexpect,py37-twisted PYTEST_COVERAGE=1
|
||||
- env: TOXENV=py37-pluggymaster-xdist
|
||||
- env: TOXENV=py37-freeze
|
||||
|
||||
# Jobs only run via Travis cron jobs (currently daily).
|
||||
- env: TOXENV=py38-xdist
|
||||
@@ -62,14 +81,20 @@ jobs:
|
||||
if: type = cron
|
||||
|
||||
- stage: baseline
|
||||
env: TOXENV=py27-pexpect,py27-trial,py27-numpy
|
||||
- env: TOXENV=py37-xdist
|
||||
- env: TOXENV=linting,docs,doctesting
|
||||
python: '3.7'
|
||||
# Coverage for:
|
||||
# - _pytest.unittest._handle_skip (via pexpect).
|
||||
env: TOXENV=py27-pexpect,py27-twisted PYTEST_COVERAGE=1
|
||||
python: '2.7'
|
||||
# Use py36 here for faster baseline.
|
||||
- env: TOXENV=py36-xdist
|
||||
python: '3.6'
|
||||
- env: TOXENV=linting,docs,doctesting PYTEST_COVERAGE=1
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pre-commit
|
||||
|
||||
- stage: deploy
|
||||
python: '3.6'
|
||||
env: PYTEST_NO_COVERAGE=1
|
||||
install: pip install -U setuptools setuptools_scm
|
||||
script: skip
|
||||
deploy:
|
||||
@@ -83,9 +108,22 @@ jobs:
|
||||
tags: true
|
||||
repo: pytest-dev/pytest
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- python: '3.8-dev'
|
||||
env: TOXENV=py38-xdist
|
||||
# Temporary (https://github.com/pytest-dev/pytest/pull/5334).
|
||||
- env: TOXENV=pypy3-xdist
|
||||
python: 'pypy3'
|
||||
|
||||
before_script:
|
||||
- |
|
||||
if [[ "$PYTEST_NO_COVERAGE" != 1 ]]; then
|
||||
# Do not (re-)upload coverage with cron runs.
|
||||
if [[ "$TRAVIS_EVENT_TYPE" = cron ]]; then
|
||||
PYTEST_COVERAGE=0
|
||||
fi
|
||||
- |
|
||||
if [[ "$PYTEST_COVERAGE" = 1 ]]; then
|
||||
export COVERAGE_FILE="$PWD/.coverage"
|
||||
export COVERAGE_PROCESS_START="$PWD/.coveragerc"
|
||||
export _PYTEST_TOX_COVERAGE_RUN="coverage run -m"
|
||||
@@ -96,14 +134,14 @@ script: tox --recreate
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [[ "$PYTEST_NO_COVERAGE" != 1 ]]; then
|
||||
if [[ "$PYTEST_COVERAGE" = 1 ]]; then
|
||||
set -e
|
||||
# Add last TOXENV to $PATH.
|
||||
PATH="$PWD/.tox/${TOXENV##*,}/bin:$PATH"
|
||||
coverage combine
|
||||
coverage xml --ignore-errors
|
||||
coverage report -m --ignore-errors
|
||||
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -F "${TOXENV//-/,},linux"
|
||||
coverage xml
|
||||
coverage report -m
|
||||
bash <(curl -s https://codecov.io/bash) -Z -X gcov -X coveragepy -X search -X xcode -X gcovout -X fix -f coverage.xml -n $TOXENV-$TRAVIS_OS_NAME
|
||||
fi
|
||||
|
||||
notifications:
|
||||
@@ -115,7 +153,3 @@ notifications:
|
||||
skip_join: true
|
||||
email:
|
||||
- pytest-commit@python.org
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.cache/pip
|
||||
- $HOME/.cache/pre-commit
|
||||
|
||||
9
AUTHORS
9
AUTHORS
@@ -9,6 +9,7 @@ Abhijeet Kasurde
|
||||
Adam Johnson
|
||||
Adam Uhlir
|
||||
Ahn Ki-Wook
|
||||
Akiomi Kamakura
|
||||
Alan Velasco
|
||||
Alexander Johnson
|
||||
Alexei Kozlenok
|
||||
@@ -59,6 +60,7 @@ Christopher Gilling
|
||||
Christopher Dignam
|
||||
CrazyMerlyn
|
||||
Cyrus Maden
|
||||
Damian Skrzypczak
|
||||
Dhiren Serai
|
||||
Daniel Grana
|
||||
Daniel Hahler
|
||||
@@ -85,6 +87,7 @@ Endre Galaczi
|
||||
Eric Hunsberger
|
||||
Eric Siegerman
|
||||
Erik M. Bray
|
||||
Evan Kepner
|
||||
Fabien Zarifian
|
||||
Fabio Zadrozny
|
||||
Feng Ma
|
||||
@@ -105,6 +108,7 @@ Hugo van Kemenade
|
||||
Hui Wang (coldnight)
|
||||
Ian Bicking
|
||||
Ian Lesperance
|
||||
Ilya Konstantinov
|
||||
Ionuț Turturică
|
||||
Iwan Briquemont
|
||||
Jaap Broekhuizen
|
||||
@@ -179,6 +183,7 @@ Nicholas Devenish
|
||||
Nicholas Murphy
|
||||
Niclas Olofsson
|
||||
Nicolas Delaby
|
||||
Nikolay Kondratyev
|
||||
Oleg Pidsadnyi
|
||||
Oleg Sushchenko
|
||||
Oliver Bestwalter
|
||||
@@ -191,6 +196,7 @@ Paweł Adamczak
|
||||
Pedro Algarvio
|
||||
Pieter Mulder
|
||||
Piotr Banaszkiewicz
|
||||
Pulkit Goyal
|
||||
Punyashloka Biswal
|
||||
Quentin Pradet
|
||||
Ralf Schmitt
|
||||
@@ -208,6 +214,7 @@ Ross Lawley
|
||||
Russel Winder
|
||||
Ryan Wooden
|
||||
Samuel Dion-Girardeau
|
||||
Samuel Searles-Bryant
|
||||
Samuele Pedroni
|
||||
Sankt Petersbug
|
||||
Segev Finer
|
||||
@@ -222,6 +229,7 @@ Steffen Allner
|
||||
Stephan Obermann
|
||||
Sven-Hendrik Haase
|
||||
Tadek Teleżyński
|
||||
Takafumi Arakaki
|
||||
Tarcisio Fischer
|
||||
Tareq Alayan
|
||||
Ted Xiao
|
||||
@@ -241,6 +249,7 @@ Vidar T. Fauske
|
||||
Virgil Dupras
|
||||
Vitaly Lashmanov
|
||||
Vlad Dragos
|
||||
Volodymyr Piskun
|
||||
Wil Cooley
|
||||
William Lee
|
||||
Wim Glenn
|
||||
|
||||
475
CHANGELOG.rst
475
CHANGELOG.rst
@@ -18,6 +18,475 @@ with advance notice in the **Deprecations** section of releases.
|
||||
|
||||
.. towncrier release notes start
|
||||
|
||||
pytest 4.6.2 (2019-06-03)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5370 <https://github.com/pytest-dev/pytest/issues/5370>`_: Revert unrolling of ``all()`` to fix ``NameError`` on nested comprehensions.
|
||||
|
||||
|
||||
- `#5371 <https://github.com/pytest-dev/pytest/issues/5371>`_: Revert unrolling of ``all()`` to fix incorrect handling of generators with ``if``.
|
||||
|
||||
|
||||
- `#5372 <https://github.com/pytest-dev/pytest/issues/5372>`_: Revert unrolling of ``all()`` to fix incorrect assertion when using ``all()`` in an expression.
|
||||
|
||||
|
||||
pytest 4.6.1 (2019-06-02)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5354 <https://github.com/pytest-dev/pytest/issues/5354>`_: Fix ``pytest.mark.parametrize`` when the argvalues is an iterator.
|
||||
|
||||
|
||||
- `#5358 <https://github.com/pytest-dev/pytest/issues/5358>`_: Fix assertion rewriting of ``all()`` calls to deal with non-generators.
|
||||
|
||||
|
||||
pytest 4.6.0 (2019-05-31)
|
||||
=========================
|
||||
|
||||
Important
|
||||
---------
|
||||
|
||||
The ``4.6.X`` series will be the last series to support **Python 2 and Python 3.4**.
|
||||
|
||||
For more details, see our `Python 2.7 and 3.4 support plan <https://docs.pytest.org/en/latest/py27-py34-deprecation.html>`__.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#4559 <https://github.com/pytest-dev/pytest/issues/4559>`_: Added the ``junit_log_passing_tests`` ini value which can be used to enable or disable logging of passing test output in the Junit XML file.
|
||||
|
||||
|
||||
- `#4956 <https://github.com/pytest-dev/pytest/issues/4956>`_: pytester's ``testdir.spawn`` uses ``tmpdir`` as HOME/USERPROFILE directory.
|
||||
|
||||
|
||||
- `#5062 <https://github.com/pytest-dev/pytest/issues/5062>`_: Unroll calls to ``all`` to full for-loops with assertion rewriting for better failure messages, especially when using Generator Expressions.
|
||||
|
||||
|
||||
- `#5063 <https://github.com/pytest-dev/pytest/issues/5063>`_: Switch from ``pkg_resources`` to ``importlib-metadata`` for entrypoint detection for improved performance and import time.
|
||||
|
||||
|
||||
- `#5091 <https://github.com/pytest-dev/pytest/issues/5091>`_: The output for ini options in ``--help`` has been improved.
|
||||
|
||||
|
||||
- `#5269 <https://github.com/pytest-dev/pytest/issues/5269>`_: ``pytest.importorskip`` includes the ``ImportError`` now in the default ``reason``.
|
||||
|
||||
|
||||
- `#5311 <https://github.com/pytest-dev/pytest/issues/5311>`_: Captured logs that are output for each failing test are formatted using the
|
||||
ColoredLevelFormatter.
|
||||
|
||||
|
||||
- `#5312 <https://github.com/pytest-dev/pytest/issues/5312>`_: Improved formatting of multiline log messages in Python 3.
|
||||
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#2064 <https://github.com/pytest-dev/pytest/issues/2064>`_: The debugging plugin imports the wrapped ``Pdb`` class (``--pdbcls``) on-demand now.
|
||||
|
||||
|
||||
- `#4908 <https://github.com/pytest-dev/pytest/issues/4908>`_: The ``pytest_enter_pdb`` hook gets called with post-mortem (``--pdb``).
|
||||
|
||||
|
||||
- `#5036 <https://github.com/pytest-dev/pytest/issues/5036>`_: Fix issue where fixtures dependent on other parametrized fixtures would be erroneously parametrized.
|
||||
|
||||
|
||||
- `#5256 <https://github.com/pytest-dev/pytest/issues/5256>`_: Handle internal error due to a lone surrogate unicode character not being representable in Jython.
|
||||
|
||||
|
||||
- `#5257 <https://github.com/pytest-dev/pytest/issues/5257>`_: Ensure that ``sys.stdout.mode`` does not include ``'b'`` as it is a text stream.
|
||||
|
||||
|
||||
- `#5278 <https://github.com/pytest-dev/pytest/issues/5278>`_: Pytest's internal python plugin can be disabled using ``-p no:python`` again.
|
||||
|
||||
|
||||
- `#5286 <https://github.com/pytest-dev/pytest/issues/5286>`_: Fix issue with ``disable_test_id_escaping_and_forfeit_all_rights_to_community_support`` option not working when using a list of test IDs in parametrized tests.
|
||||
|
||||
|
||||
- `#5330 <https://github.com/pytest-dev/pytest/issues/5330>`_: Show the test module being collected when emitting ``PytestCollectionWarning`` messages for
|
||||
test classes with ``__init__`` and ``__new__`` methods to make it easier to pin down the problem.
|
||||
|
||||
|
||||
- `#5333 <https://github.com/pytest-dev/pytest/issues/5333>`_: Fix regression in 4.5.0 with ``--lf`` not re-running all tests with known failures from non-selected tests.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#5250 <https://github.com/pytest-dev/pytest/issues/5250>`_: Expand docs on use of ``setenv`` and ``delenv`` with ``monkeypatch``.
|
||||
|
||||
|
||||
pytest 4.5.0 (2019-05-11)
|
||||
=========================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#4826 <https://github.com/pytest-dev/pytest/issues/4826>`_: A warning is now emitted when unknown marks are used as a decorator.
|
||||
This is often due to a typo, which can lead to silently broken tests.
|
||||
|
||||
|
||||
- `#4907 <https://github.com/pytest-dev/pytest/issues/4907>`_: Show XFail reason as part of JUnitXML message field.
|
||||
|
||||
|
||||
- `#5013 <https://github.com/pytest-dev/pytest/issues/5013>`_: Messages from crash reports are displayed within test summaries now, truncated to the terminal width.
|
||||
|
||||
|
||||
- `#5023 <https://github.com/pytest-dev/pytest/issues/5023>`_: New flag ``--strict-markers`` that triggers an error when unknown markers (e.g. those not registered using the `markers option`_ in the configuration file) are used in the test suite.
|
||||
|
||||
The existing ``--strict`` option has the same behavior currently, but can be augmented in the future for additional checks.
|
||||
|
||||
.. _`markers option`: https://docs.pytest.org/en/latest/reference.html#confval-markers
|
||||
|
||||
|
||||
- `#5026 <https://github.com/pytest-dev/pytest/issues/5026>`_: Assertion failure messages for sequences and dicts contain the number of different items now.
|
||||
|
||||
|
||||
- `#5034 <https://github.com/pytest-dev/pytest/issues/5034>`_: Improve reporting with ``--lf`` and ``--ff`` (run-last-failure).
|
||||
|
||||
|
||||
- `#5035 <https://github.com/pytest-dev/pytest/issues/5035>`_: The ``--cache-show`` option/action accepts an optional glob to show only matching cache entries.
|
||||
|
||||
|
||||
- `#5059 <https://github.com/pytest-dev/pytest/issues/5059>`_: Standard input (stdin) can be given to pytester's ``Testdir.run()`` and ``Testdir.popen()``.
|
||||
|
||||
|
||||
- `#5068 <https://github.com/pytest-dev/pytest/issues/5068>`_: The ``-r`` option learnt about ``A`` to display all reports (including passed ones) in the short test summary.
|
||||
|
||||
|
||||
- `#5108 <https://github.com/pytest-dev/pytest/issues/5108>`_: The short test summary is displayed after passes with output (``-rP``).
|
||||
|
||||
|
||||
- `#5172 <https://github.com/pytest-dev/pytest/issues/5172>`_: The ``--last-failed`` (``--lf``) option got smarter and will now skip entire files if all tests
|
||||
of that test file have passed in previous runs, greatly speeding up collection.
|
||||
|
||||
|
||||
- `#5177 <https://github.com/pytest-dev/pytest/issues/5177>`_: Introduce new specific warning ``PytestWarning`` subclasses to make it easier to filter warnings based on the class, rather than on the message. The new subclasses are:
|
||||
|
||||
|
||||
* ``PytestAssertRewriteWarning``
|
||||
|
||||
* ``PytestCacheWarning``
|
||||
|
||||
* ``PytestCollectionWarning``
|
||||
|
||||
* ``PytestConfigWarning``
|
||||
|
||||
* ``PytestUnhandledCoroutineWarning``
|
||||
|
||||
* ``PytestUnknownMarkWarning``
|
||||
|
||||
|
||||
- `#5202 <https://github.com/pytest-dev/pytest/issues/5202>`_: New ``record_testsuite_property`` session-scoped fixture allows users to log ``<property>`` tags at the ``testsuite``
|
||||
level with the ``junitxml`` plugin.
|
||||
|
||||
The generated XML is compatible with the latest xunit standard, contrary to
|
||||
the properties recorded by ``record_property`` and ``record_xml_attribute``.
|
||||
|
||||
|
||||
- `#5214 <https://github.com/pytest-dev/pytest/issues/5214>`_: The default logging format has been changed to improve readability. Here is an
|
||||
example of a previous logging message::
|
||||
|
||||
test_log_cli_enabled_disabled.py 3 CRITICAL critical message logged by test
|
||||
|
||||
This has now become::
|
||||
|
||||
CRITICAL root:test_log_cli_enabled_disabled.py:3 critical message logged by test
|
||||
|
||||
The formatting can be changed through the `log_format <https://docs.pytest.org/en/latest/reference.html#confval-log_format>`__ configuration option.
|
||||
|
||||
|
||||
- `#5220 <https://github.com/pytest-dev/pytest/issues/5220>`_: ``--fixtures`` now also shows fixture scope for scopes other than ``"function"``.
|
||||
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5113 <https://github.com/pytest-dev/pytest/issues/5113>`_: Deselected items from plugins using ``pytest_collect_modifyitems`` as a hookwrapper are correctly reported now.
|
||||
|
||||
|
||||
- `#5144 <https://github.com/pytest-dev/pytest/issues/5144>`_: With usage errors ``exitstatus`` is set to ``EXIT_USAGEERROR`` in the ``pytest_sessionfinish`` hook now as expected.
|
||||
|
||||
|
||||
- `#5235 <https://github.com/pytest-dev/pytest/issues/5235>`_: ``outcome.exit`` is not used with ``EOF`` in the pdb wrapper anymore, but only with ``quit``.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#4935 <https://github.com/pytest-dev/pytest/issues/4935>`_: Expand docs on registering marks and the effect of ``--strict``.
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#4942 <https://github.com/pytest-dev/pytest/issues/4942>`_: ``logging.raiseExceptions`` is not set to ``False`` anymore.
|
||||
|
||||
|
||||
- `#5013 <https://github.com/pytest-dev/pytest/issues/5013>`_: pytest now depends on `wcwidth <https://pypi.org/project/wcwidth>`__ to properly track unicode character sizes for more precise terminal output.
|
||||
|
||||
|
||||
- `#5059 <https://github.com/pytest-dev/pytest/issues/5059>`_: pytester's ``Testdir.popen()`` uses ``stdout`` and ``stderr`` via keyword arguments with defaults now (``subprocess.PIPE``).
|
||||
|
||||
|
||||
- `#5069 <https://github.com/pytest-dev/pytest/issues/5069>`_: The code for the short test summary in the terminal was moved to the terminal plugin.
|
||||
|
||||
|
||||
- `#5082 <https://github.com/pytest-dev/pytest/issues/5082>`_: Improved validation of kwargs for various methods in the pytester plugin.
|
||||
|
||||
|
||||
- `#5202 <https://github.com/pytest-dev/pytest/issues/5202>`_: ``record_property`` now emits a ``PytestWarning`` when used with ``junit_family=xunit2``: the fixture generates
|
||||
``property`` tags as children of ``testcase``, which is not permitted according to the most
|
||||
`recent schema <https://github.com/jenkinsci/xunit-plugin/blob/master/
|
||||
src/main/resources/org/jenkinsci/plugins/xunit/types/model/xsd/junit-10.xsd>`__.
|
||||
|
||||
|
||||
- `#5239 <https://github.com/pytest-dev/pytest/issues/5239>`_: Pin ``pluggy`` to ``< 1.0`` so we don't update to ``1.0`` automatically when
|
||||
it gets released: there are planned breaking changes, and we want to ensure
|
||||
pytest properly supports ``pluggy 1.0``.
|
||||
|
||||
|
||||
pytest 4.4.2 (2019-05-08)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5089 <https://github.com/pytest-dev/pytest/issues/5089>`_: Fix crash caused by error in ``__repr__`` function with both ``showlocals`` and verbose output enabled.
|
||||
|
||||
|
||||
- `#5139 <https://github.com/pytest-dev/pytest/issues/5139>`_: Eliminate core dependency on 'terminal' plugin.
|
||||
|
||||
|
||||
- `#5229 <https://github.com/pytest-dev/pytest/issues/5229>`_: Require ``pluggy>=0.11.0`` which reverts a dependency to ``importlib-metadata`` added in ``0.10.0``.
|
||||
The ``importlib-metadata`` package cannot be imported when installed as an egg and causes issues when relying on ``setup.py`` to install test dependencies.
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#5171 <https://github.com/pytest-dev/pytest/issues/5171>`_: Doc: ``pytest_ignore_collect``, ``pytest_collect_directory``, ``pytest_collect_file`` and ``pytest_pycollect_makemodule`` hooks's 'path' parameter documented type is now ``py.path.local``
|
||||
|
||||
|
||||
- `#5188 <https://github.com/pytest-dev/pytest/issues/5188>`_: Improve help for ``--runxfail`` flag.
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#5182 <https://github.com/pytest-dev/pytest/issues/5182>`_: Removed internal and unused ``_pytest.deprecated.MARK_INFO_ATTRIBUTE``.
|
||||
|
||||
|
||||
pytest 4.4.1 (2019-04-15)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#5031 <https://github.com/pytest-dev/pytest/issues/5031>`_: Environment variables are properly restored when using pytester's ``testdir`` fixture.
|
||||
|
||||
|
||||
- `#5039 <https://github.com/pytest-dev/pytest/issues/5039>`_: Fix regression with ``--pdbcls``, which stopped working with local modules in 4.0.0.
|
||||
|
||||
|
||||
- `#5092 <https://github.com/pytest-dev/pytest/issues/5092>`_: Produce a warning when unknown keywords are passed to ``pytest.param(...)``.
|
||||
|
||||
|
||||
- `#5098 <https://github.com/pytest-dev/pytest/issues/5098>`_: Invalidate import caches with ``monkeypatch.syspath_prepend``, which is required with namespace packages being used.
|
||||
|
||||
|
||||
pytest 4.4.0 (2019-03-29)
|
||||
=========================
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- `#2224 <https://github.com/pytest-dev/pytest/issues/2224>`_: ``async`` test functions are skipped and a warning is emitted when a suitable
|
||||
async plugin is not installed (such as ``pytest-asyncio`` or ``pytest-trio``).
|
||||
|
||||
Previously ``async`` functions would not execute at all but still be marked as "passed".
|
||||
|
||||
|
||||
- `#2482 <https://github.com/pytest-dev/pytest/issues/2482>`_: Include new ``disable_test_id_escaping_and_forfeit_all_rights_to_community_support`` option to disable ascii-escaping in parametrized values. This may cause a series of problems and as the name makes clear, use at your own risk.
|
||||
|
||||
|
||||
- `#4718 <https://github.com/pytest-dev/pytest/issues/4718>`_: The ``-p`` option can now be used to early-load plugins also by entry-point name, instead of just
|
||||
by module name.
|
||||
|
||||
This makes it possible to early load external plugins like ``pytest-cov`` in the command-line::
|
||||
|
||||
pytest -p pytest_cov
|
||||
|
||||
|
||||
- `#4855 <https://github.com/pytest-dev/pytest/issues/4855>`_: The ``--pdbcls`` option handles classes via module attributes now (e.g.
|
||||
``pdb:pdb.Pdb`` with `pdb++`_), and its validation was improved.
|
||||
|
||||
.. _pdb++: https://pypi.org/project/pdbpp/
|
||||
|
||||
|
||||
- `#4875 <https://github.com/pytest-dev/pytest/issues/4875>`_: The `testpaths <https://docs.pytest.org/en/latest/reference.html#confval-testpaths>`__ configuration option is now displayed next
|
||||
to the ``rootdir`` and ``inifile`` lines in the pytest header if the option is in effect, i.e., directories or file names were
|
||||
not explicitly passed in the command line.
|
||||
|
||||
Also, ``inifile`` is only displayed if there's a configuration file, instead of an empty ``inifile:`` string.
|
||||
|
||||
|
||||
- `#4911 <https://github.com/pytest-dev/pytest/issues/4911>`_: Doctests can be skipped now dynamically using ``pytest.skip()``.
|
||||
|
||||
|
||||
- `#4920 <https://github.com/pytest-dev/pytest/issues/4920>`_: Internal refactorings have been made in order to make the implementation of the
|
||||
`pytest-subtests <https://github.com/pytest-dev/pytest-subtests>`__ plugin
|
||||
possible, which adds unittest sub-test support and a new ``subtests`` fixture as discussed in
|
||||
`#1367 <https://github.com/pytest-dev/pytest/issues/1367>`__.
|
||||
|
||||
For details on the internal refactorings, please see the details on the related PR.
|
||||
|
||||
|
||||
- `#4931 <https://github.com/pytest-dev/pytest/issues/4931>`_: pytester's ``LineMatcher`` asserts that the passed lines are a sequence.
|
||||
|
||||
|
||||
- `#4936 <https://github.com/pytest-dev/pytest/issues/4936>`_: Handle ``-p plug`` after ``-p no:plug``.
|
||||
|
||||
This can be used to override a blocked plugin (e.g. in "addopts") from the
|
||||
command line etc.
|
||||
|
||||
|
||||
- `#4951 <https://github.com/pytest-dev/pytest/issues/4951>`_: Output capturing is handled correctly when only capturing via fixtures (capsys, capfs) with ``pdb.set_trace()``.
|
||||
|
||||
|
||||
- `#4956 <https://github.com/pytest-dev/pytest/issues/4956>`_: ``pytester`` sets ``$HOME`` and ``$USERPROFILE`` to the temporary directory during test runs.
|
||||
|
||||
This ensures to not load configuration files from the real user's home directory.
|
||||
|
||||
|
||||
- `#4980 <https://github.com/pytest-dev/pytest/issues/4980>`_: Namespace packages are handled better with ``monkeypatch.syspath_prepend`` and ``testdir.syspathinsert`` (via ``pkg_resources.fixup_namespace_packages``).
|
||||
|
||||
|
||||
- `#4993 <https://github.com/pytest-dev/pytest/issues/4993>`_: The stepwise plugin reports status information now.
|
||||
|
||||
|
||||
- `#5008 <https://github.com/pytest-dev/pytest/issues/5008>`_: If a ``setup.cfg`` file contains ``[tool:pytest]`` and also the no longer supported ``[pytest]`` section, pytest will use ``[tool:pytest]`` ignoring ``[pytest]``. Previously it would unconditionally error out.
|
||||
|
||||
This makes it simpler for plugins to support old pytest versions.
|
||||
|
||||
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#1895 <https://github.com/pytest-dev/pytest/issues/1895>`_: Fix bug where fixtures requested dynamically via ``request.getfixturevalue()`` might be teardown
|
||||
before the requesting fixture.
|
||||
|
||||
|
||||
- `#4851 <https://github.com/pytest-dev/pytest/issues/4851>`_: pytester unsets ``PYTEST_ADDOPTS`` now to not use outer options with ``testdir.runpytest()``.
|
||||
|
||||
|
||||
- `#4903 <https://github.com/pytest-dev/pytest/issues/4903>`_: Use the correct modified time for years after 2038 in rewritten ``.pyc`` files.
|
||||
|
||||
|
||||
- `#4928 <https://github.com/pytest-dev/pytest/issues/4928>`_: Fix line offsets with ``ScopeMismatch`` errors.
|
||||
|
||||
|
||||
- `#4957 <https://github.com/pytest-dev/pytest/issues/4957>`_: ``-p no:plugin`` is handled correctly for default (internal) plugins now, e.g. with ``-p no:capture``.
|
||||
|
||||
Previously they were loaded (imported) always, making e.g. the ``capfd`` fixture available.
|
||||
|
||||
|
||||
- `#4968 <https://github.com/pytest-dev/pytest/issues/4968>`_: The pdb ``quit`` command is handled properly when used after the ``debug`` command with `pdb++`_.
|
||||
|
||||
.. _pdb++: https://pypi.org/project/pdbpp/
|
||||
|
||||
|
||||
- `#4975 <https://github.com/pytest-dev/pytest/issues/4975>`_: Fix the interpretation of ``-qq`` option where it was being considered as ``-v`` instead.
|
||||
|
||||
|
||||
- `#4978 <https://github.com/pytest-dev/pytest/issues/4978>`_: ``outcomes.Exit`` is not swallowed in ``assertrepr_compare`` anymore.
|
||||
|
||||
|
||||
- `#4988 <https://github.com/pytest-dev/pytest/issues/4988>`_: Close logging's file handler explicitly when the session finishes.
|
||||
|
||||
|
||||
- `#5003 <https://github.com/pytest-dev/pytest/issues/5003>`_: Fix line offset with mark collection error (off by one).
|
||||
|
||||
|
||||
|
||||
Improved Documentation
|
||||
----------------------
|
||||
|
||||
- `#4974 <https://github.com/pytest-dev/pytest/issues/4974>`_: Update docs for ``pytest_cmdline_parse`` hook to note availability liminations
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#4718 <https://github.com/pytest-dev/pytest/issues/4718>`_: ``pluggy>=0.9`` is now required.
|
||||
|
||||
|
||||
- `#4815 <https://github.com/pytest-dev/pytest/issues/4815>`_: ``funcsigs>=1.0`` is now required for Python 2.7.
|
||||
|
||||
|
||||
- `#4829 <https://github.com/pytest-dev/pytest/issues/4829>`_: Some left-over internal code related to ``yield`` tests has been removed.
|
||||
|
||||
|
||||
- `#4890 <https://github.com/pytest-dev/pytest/issues/4890>`_: Remove internally unused ``anypython`` fixture from the pytester plugin.
|
||||
|
||||
|
||||
- `#4912 <https://github.com/pytest-dev/pytest/issues/4912>`_: Remove deprecated Sphinx directive, ``add_description_unit()``,
|
||||
pin sphinx-removed-in to >= 0.2.0 to support Sphinx 2.0.
|
||||
|
||||
|
||||
- `#4913 <https://github.com/pytest-dev/pytest/issues/4913>`_: Fix pytest tests invocation with custom ``PYTHONPATH``.
|
||||
|
||||
|
||||
- `#4965 <https://github.com/pytest-dev/pytest/issues/4965>`_: New ``pytest_report_to_serializable`` and ``pytest_report_from_serializable`` **experimental** hooks.
|
||||
|
||||
These hooks will be used by ``pytest-xdist``, ``pytest-subtests``, and the replacement for
|
||||
resultlog to serialize and customize reports.
|
||||
|
||||
They are experimental, meaning that their details might change or even be removed
|
||||
completely in future patch releases without warning.
|
||||
|
||||
Feedback is welcome from plugin authors and users alike.
|
||||
|
||||
|
||||
- `#4987 <https://github.com/pytest-dev/pytest/issues/4987>`_: ``Collector.repr_failure`` respects the ``--tb`` option, but only defaults to ``short`` now (with ``auto``).
|
||||
|
||||
|
||||
pytest 4.3.1 (2019-03-11)
|
||||
=========================
|
||||
|
||||
Bug Fixes
|
||||
---------
|
||||
|
||||
- `#4810 <https://github.com/pytest-dev/pytest/issues/4810>`_: Logging messages inside ``pytest_runtest_logreport()`` are now properly captured and displayed.
|
||||
|
||||
|
||||
- `#4861 <https://github.com/pytest-dev/pytest/issues/4861>`_: Improve validation of contents written to captured output so it behaves the same as when capture is disabled.
|
||||
|
||||
|
||||
- `#4898 <https://github.com/pytest-dev/pytest/issues/4898>`_: Fix ``AttributeError: FixtureRequest has no 'confg' attribute`` bug in ``testdir.copy_example``.
|
||||
|
||||
|
||||
|
||||
Trivial/Internal Changes
|
||||
------------------------
|
||||
|
||||
- `#4768 <https://github.com/pytest-dev/pytest/issues/4768>`_: Avoid pkg_resources import at the top-level.
|
||||
|
||||
|
||||
pytest 4.3.0 (2019-02-16)
|
||||
=========================
|
||||
|
||||
@@ -263,7 +732,7 @@ Removals
|
||||
See our `docs <https://docs.pytest.org/en/latest/deprecations.html#passing-command-line-string-to-pytest-main>`__ on information on how to update your code.
|
||||
|
||||
|
||||
- `#3086 <https://github.com/pytest-dev/pytest/issues/3086>`_: ``[pytest]`` section in **setup.cfg** files is not longer supported, use ``[tool:pytest]`` instead. ``setup.cfg`` files
|
||||
- `#3086 <https://github.com/pytest-dev/pytest/issues/3086>`_: ``[pytest]`` section in **setup.cfg** files is no longer supported, use ``[tool:pytest]`` instead. ``setup.cfg`` files
|
||||
are meant for use with ``distutils``, and a section named ``pytest`` has notoriously been a source of conflicts and bugs.
|
||||
|
||||
Note that for **pytest.ini** and **tox.ini** files the section remains ``[pytest]``.
|
||||
@@ -1266,7 +1735,7 @@ Bug Fixes
|
||||
- `#2220 <https://github.com/pytest-dev/pytest/issues/2220>`_: Fix a bug where fixtures overridden by direct parameters (for example parametrization) were being instantiated even if they were not being used by a test.
|
||||
|
||||
|
||||
- `#3695 <https://github.com/pytest-dev/pytest/issues/3695>`_: Fix ``ApproxNumpy`` initialisation argument mixup, ``abs`` and ``rel`` tolerances were flipped causing strange comparsion results.
|
||||
- `#3695 <https://github.com/pytest-dev/pytest/issues/3695>`_: Fix ``ApproxNumpy`` initialisation argument mixup, ``abs`` and ``rel`` tolerances were flipped causing strange comparison results.
|
||||
Add tests to check ``abs`` and ``rel`` tolerances for ``np.array`` and test for expecting ``nan`` with ``np.array()``
|
||||
|
||||
|
||||
@@ -1485,7 +1954,7 @@ Features
|
||||
exits the debugger. On python 3.2 and higher, use CTRL+D. (`#3299
|
||||
<https://github.com/pytest-dev/pytest/issues/3299>`_)
|
||||
|
||||
- pytest not longer changes the log level of the root logger when the
|
||||
- pytest no longer changes the log level of the root logger when the
|
||||
``log-level`` parameter has greater numeric value than that of the level of
|
||||
the root logger, which makes it play better with custom logging configuration
|
||||
in user code. (`#3307 <https://github.com/pytest-dev/pytest/issues/3307>`_)
|
||||
|
||||
@@ -166,7 +166,7 @@ Short version
|
||||
#. Enable and install `pre-commit <https://pre-commit.com>`_ to ensure style-guides and code checks are followed.
|
||||
#. Target ``master`` for bugfixes and doc changes.
|
||||
#. Target ``features`` for new features or functionality changes.
|
||||
#. Follow **PEP-8** for naming and `black <https://github.com/ambv/black>`_ for formatting.
|
||||
#. Follow **PEP-8** for naming and `black <https://github.com/python/black>`_ for formatting.
|
||||
#. Tests are run using ``tox``::
|
||||
|
||||
tox -e linting,py27,py37
|
||||
|
||||
26
README.rst
26
README.rst
@@ -22,11 +22,11 @@
|
||||
.. image:: https://travis-ci.org/pytest-dev/pytest.svg?branch=master
|
||||
:target: https://travis-ci.org/pytest-dev/pytest
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/mrgbjaua7t33pg6b?svg=true
|
||||
:target: https://ci.appveyor.com/project/pytestbot/pytest
|
||||
.. image:: https://dev.azure.com/pytest-dev/pytest/_apis/build/status/pytest-CI?branchName=master
|
||||
:target: https://dev.azure.com/pytest-dev/pytest
|
||||
|
||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
||||
:target: https://github.com/ambv/black
|
||||
:target: https://github.com/python/black
|
||||
|
||||
.. image:: https://www.codetriage.com/pytest-dev/pytest/badges/users.svg
|
||||
:target: https://www.codetriage.com/pytest-dev/pytest
|
||||
@@ -108,6 +108,26 @@ Changelog
|
||||
Consult the `Changelog <https://docs.pytest.org/en/latest/changelog.html>`__ page for fixes and enhancements of each version.
|
||||
|
||||
|
||||
Support pytest
|
||||
--------------
|
||||
|
||||
You can support pytest by obtaining a `Tideflift subscription`_.
|
||||
|
||||
Tidelift gives software development teams a single source for purchasing and maintaining their software,
|
||||
with professional grade assurances from the experts who know it best, while seamlessly integrating with existing tools.
|
||||
|
||||
|
||||
.. _`Tideflift subscription`: https://tidelift.com/subscription/pkg/pypi-pytest?utm_source=pypi-pytest&utm_medium=referral&utm_campaign=readme
|
||||
|
||||
|
||||
Security
|
||||
^^^^^^^^
|
||||
|
||||
pytest has never been associated with a security vunerability, but in any case, to report a
|
||||
security vulnerability please use the `Tidelift security contact <https://tidelift.com/security>`_.
|
||||
Tidelift will coordinate the fix and disclosure.
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
|
||||
57
TIDELIFT.rst
Normal file
57
TIDELIFT.rst
Normal file
@@ -0,0 +1,57 @@
|
||||
========
|
||||
Tidelift
|
||||
========
|
||||
|
||||
pytest is a member of `Tidelift`_. This document describes how the core team manages
|
||||
Tidelift-related activities.
|
||||
|
||||
What is it
|
||||
==========
|
||||
|
||||
Tidelift aims to make Open Source sustainable by offering subscriptions to companies which rely
|
||||
on Open Source packages. This subscription allows it to pay maintainers of those Open Source
|
||||
packages to aid sustainability of the work.
|
||||
|
||||
Funds
|
||||
=====
|
||||
|
||||
It was decided in the `mailing list`_ that the Tidelift contribution will be split evenly between
|
||||
members of the `contributors team`_ interested in receiving funding.
|
||||
|
||||
The current list of contributors receiving funding are:
|
||||
|
||||
* `@asottile`_
|
||||
* `@blueyed`_
|
||||
* `@nicoddemus`_
|
||||
|
||||
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
|
||||
in the same way.
|
||||
|
||||
The PR should mention `@pytest-dev/tidelift-admins`_ so appropriate changes
|
||||
can be made in the Tidelift platform.
|
||||
|
||||
After the PR has been accepted and merged, the contributor should register in the `Tidelift`_
|
||||
platform and follow the instructions there, including signing an `agreement`_.
|
||||
|
||||
Admins
|
||||
======
|
||||
|
||||
A few people have admin access to the Tidelift dashboard to make changes. Those people
|
||||
are part of the `@pytest-dev/tidelift-admins`_ team.
|
||||
|
||||
`Core contributors`_ interested in helping out with Tidelift maintenance are welcome! We don't
|
||||
expect much work here other than the occasional adding/removal of a contributor from receiving
|
||||
funds. Just drop a line to one of the `@pytest-dev/tidelift-admins`_ or use the mailing list.
|
||||
|
||||
|
||||
.. _`Tidelift`: https://tidelift.com
|
||||
.. _`mailing list`: https://mail.python.org/pipermail/pytest-dev/2019-May/004716.html
|
||||
.. _`contributors team`: https://github.com/orgs/pytest-dev/teams/contributors
|
||||
.. _`core contributors`: https://github.com/orgs/pytest-dev/teams/core/members
|
||||
.. _`@pytest-dev/tidelift-admins`: https://github.com/orgs/pytest-dev/teams/tidelift-admins/members
|
||||
.. _`agreement`: https://tidelift.com/docs/lifting/agreement
|
||||
|
||||
.. _`@asottile`: https://github.com/asottile
|
||||
.. _`@blueyed`: https://github.com/blueyed
|
||||
.. _`@nicoddemus`: https://github.com/nicoddemus
|
||||
49
appveyor.yml
49
appveyor.yml
@@ -1,49 +0,0 @@
|
||||
environment:
|
||||
matrix:
|
||||
- TOXENV: "py37-xdist"
|
||||
- TOXENV: "py27-xdist"
|
||||
- TOXENV: "linting,docs,doctesting"
|
||||
- TOXENV: "py34-xdist"
|
||||
- TOXENV: "py35-xdist"
|
||||
- TOXENV: "py36-xdist"
|
||||
- TOXENV: "pypy"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
# Specialized factors for py27.
|
||||
- TOXENV: "py27-trial,py27-numpy,py27-nobyte"
|
||||
- TOXENV: "py27-pluggymaster"
|
||||
# Specialized factors for py37.
|
||||
- TOXENV: "py37-trial,py37-numpy"
|
||||
- TOXENV: "py37-pluggymaster"
|
||||
- TOXENV: "py37-freeze"
|
||||
PYTEST_NO_COVERAGE: "1"
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
install:
|
||||
- echo Installed Pythons
|
||||
- dir c:\Python*
|
||||
|
||||
- if "%TOXENV%" == "pypy" call scripts\install-pypy.bat
|
||||
|
||||
- C:\Python36\python -m pip install --upgrade pip
|
||||
- C:\Python36\python -m pip install --upgrade --pre tox
|
||||
|
||||
build: false # Not a C# project, build stuff at the test step instead.
|
||||
|
||||
before_test:
|
||||
- call scripts\prepare-coverage.bat
|
||||
|
||||
test_script:
|
||||
- C:\Python36\python -m tox
|
||||
|
||||
on_success:
|
||||
- call scripts\upload-coverage.bat
|
||||
|
||||
cache:
|
||||
- '%LOCALAPPDATA%\pip\cache'
|
||||
- '%USERPROFILE%\.cache\pre-commit'
|
||||
|
||||
# We don't deploy anything on tags with AppVeyor, we use Travis instead, so we
|
||||
# might as well save resources
|
||||
skip_tags: true
|
||||
@@ -3,7 +3,11 @@ trigger:
|
||||
- features
|
||||
|
||||
variables:
|
||||
PYTEST_ADDOPTS: "--junitxml=build/test-results/$(tox.env).xml"
|
||||
PYTEST_ADDOPTS: "--junitxml=build/test-results/$(tox.env).xml -vv"
|
||||
python.needs_vc: False
|
||||
COVERAGE_FILE: "$(Build.Repository.LocalPath)/.coverage"
|
||||
COVERAGE_PROCESS_START: "$(Build.Repository.LocalPath)/.coveragerc"
|
||||
PYTEST_COVERAGE: '0'
|
||||
|
||||
jobs:
|
||||
|
||||
@@ -15,16 +19,67 @@ jobs:
|
||||
py27:
|
||||
python.version: '2.7'
|
||||
tox.env: 'py27'
|
||||
py35:
|
||||
py27-nobyte-lsof-numpy:
|
||||
python.version: '2.7'
|
||||
tox.env: 'py27-lsof-nobyte-numpy'
|
||||
# Coverage for:
|
||||
# - test_supports_breakpoint_module_global
|
||||
# - test_terminal_reporter_writer_attr (without xdist)
|
||||
# - "if write" branch in _pytest.assertion.rewrite
|
||||
# - numpy
|
||||
# - pytester's LsofFdLeakChecker (being skipped)
|
||||
PYTEST_COVERAGE: '1'
|
||||
py27-twisted:
|
||||
python.version: '2.7'
|
||||
tox.env: 'py27-twisted'
|
||||
python.needs_vc: True
|
||||
py27-pluggymaster-xdist:
|
||||
python.version: '2.7'
|
||||
tox.env: 'py27-pluggymaster-xdist'
|
||||
# Coverage for:
|
||||
# - except-IOError in _attempt_to_close_capture_file for py2.
|
||||
# Also seen with py27-nobyte (using xdist), and py27-xdist.
|
||||
# But no exception with py27-pexpect,py27-twisted,py27-numpy.
|
||||
PYTEST_COVERAGE: '1'
|
||||
# -- pypy2 and pypy3 are disabled for now: #5279 --
|
||||
# pypy:
|
||||
# python.version: 'pypy2'
|
||||
# tox.env: 'pypy'
|
||||
# pypy3:
|
||||
# python.version: 'pypy3'
|
||||
# tox.env: 'pypy3'
|
||||
py34-xdist:
|
||||
python.version: '3.4'
|
||||
tox.env: 'py34-xdist'
|
||||
# Coverage for:
|
||||
# - _pytest.compat._bytes_to_ascii
|
||||
PYTEST_COVERAGE: '1'
|
||||
py35-xdist:
|
||||
python.version: '3.5'
|
||||
tox.env: 'py35'
|
||||
py36:
|
||||
tox.env: 'py35-xdist'
|
||||
# Coverage for:
|
||||
# - test_supports_breakpoint_module_global
|
||||
PYTEST_COVERAGE: '1'
|
||||
py36-xdist:
|
||||
python.version: '3.6'
|
||||
tox.env: 'py36'
|
||||
tox.env: 'py36-xdist'
|
||||
py37:
|
||||
python.version: '3.7'
|
||||
tox.env: 'py37'
|
||||
maxParallel: 4
|
||||
# Coverage for:
|
||||
# - _py36_windowsconsoleio_workaround (with py36+)
|
||||
# - test_request_garbage (no xdist)
|
||||
PYTEST_COVERAGE: '1'
|
||||
py37-linting/docs/doctesting:
|
||||
python.version: '3.7'
|
||||
tox.env: 'linting,docs,doctesting'
|
||||
py37-twisted/numpy:
|
||||
python.version: '3.7'
|
||||
tox.env: 'py37-twisted,py37-numpy'
|
||||
py37-pluggymaster-xdist:
|
||||
python.version: '3.7'
|
||||
tox.env: 'py37-pluggymaster-xdist'
|
||||
maxParallel: 10
|
||||
|
||||
steps:
|
||||
- task: UsePythonVersion@0
|
||||
@@ -32,10 +87,16 @@ jobs:
|
||||
versionSpec: '$(python.version)'
|
||||
architecture: 'x64'
|
||||
|
||||
- script: python -m pip install --upgrade pip && pip install tox
|
||||
- script: choco install vcpython27
|
||||
condition: eq(variables['python.needs_vc'], True)
|
||||
displayName: 'Install VC for py27'
|
||||
|
||||
- script: python -m pip install --upgrade pip && python -m pip install tox
|
||||
displayName: 'Install tox'
|
||||
|
||||
- script: python -m tox -e $(tox.env)
|
||||
- script: |
|
||||
call scripts/setup-coverage-vars.bat || goto :eof
|
||||
python -m tox -e $(tox.env)
|
||||
displayName: 'Run tests'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
@@ -43,3 +104,10 @@ jobs:
|
||||
testResultsFiles: 'build/test-results/$(tox.env).xml'
|
||||
testRunTitle: '$(tox.env)'
|
||||
condition: succeededOrFailed()
|
||||
|
||||
- script: call scripts\upload-coverage.bat
|
||||
displayName: 'Report and upload coverage'
|
||||
condition: eq(variables['PYTEST_COVERAGE'], '1')
|
||||
env:
|
||||
CODECOV_TOKEN: $(CODECOV_TOKEN)
|
||||
PYTEST_CODECOV_NAME: $(tox.env)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
@@ -5,7 +6,7 @@ if __name__ == "__main__":
|
||||
import pytest # NOQA
|
||||
import pstats
|
||||
|
||||
script = sys.argv[1:] if len(sys.argv) > 1 else "empty.py"
|
||||
script = sys.argv[1:] if len(sys.argv) > 1 else ["empty.py"]
|
||||
stats = cProfile.run("pytest.cmdline.main(%r)" % script, "prof")
|
||||
p = pstats.Stats("prof")
|
||||
p.strip_dirs()
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 10000 iterations, just for relative comparison
|
||||
# 2.7.5 3.3.2
|
||||
# FilesCompleter 75.1109 69.2116
|
||||
@@ -16,4 +17,4 @@ run = 'fc("/d")'
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(timeit.timeit(run, setup=setup % imports[0], number=count))
|
||||
print((timeit.timeit(run, setup=setup % imports[1], number=count)))
|
||||
print(timeit.timeit(run, setup=setup % imports[1], number=count))
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import six
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
for i in range(1000):
|
||||
six.exec_("def test_func_%d(): pass" % i)
|
||||
exec("def test_func_%d(): pass" % i)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from six.moves import range
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
SKIP = True
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||
|
||||
REGENDOC_ARGS := \
|
||||
--normalize "/[ \t]+\n/\n/" \
|
||||
--normalize "~\$$REGENDOC_TMPDIR~/home/sweet/project~" \
|
||||
--normalize "~/path/to/example~/home/sweet/project~" \
|
||||
--normalize "/in \d+.\d+ seconds/in 0.12 seconds/" \
|
||||
--normalize "@/tmp/pytest-of-.*/pytest-\d+@PYTEST_TMPDIR@" \
|
||||
--normalize "@pytest-(\d+)\\.[^ ,]+@pytest-\1.x.y@" \
|
||||
@@ -38,8 +41,9 @@ help:
|
||||
clean:
|
||||
-rm -rf $(BUILDDIR)/*
|
||||
|
||||
regen: REGENDOC_FILES:=*.rst */*.rst
|
||||
regen:
|
||||
PYTHONDONTWRITEBYTECODE=1 PYTEST_ADDOPTS=-pno:hypothesis COLUMNS=76 regendoc --update *.rst */*.rst ${REGENDOC_ARGS}
|
||||
PYTHONDONTWRITEBYTECODE=1 PYTEST_ADDOPTS="-pno:hypothesis -Wignore::pytest.PytestUnknownMarkWarning" COLUMNS=76 regendoc --update ${REGENDOC_FILES} ${REGENDOC_ARGS}
|
||||
|
||||
html:
|
||||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# flasky extensions. flasky pygments style based on tango style
|
||||
from pygments.style import Style
|
||||
from pygments.token import Comment
|
||||
|
||||
@@ -6,6 +6,14 @@ Release announcements
|
||||
:maxdepth: 2
|
||||
|
||||
|
||||
release-4.6.2
|
||||
release-4.6.1
|
||||
release-4.6.0
|
||||
release-4.5.0
|
||||
release-4.4.2
|
||||
release-4.4.1
|
||||
release-4.4.0
|
||||
release-4.3.1
|
||||
release-4.3.0
|
||||
release-4.2.1
|
||||
release-4.2.0
|
||||
|
||||
29
doc/en/announce/release-4.3.1.rst
Normal file
29
doc/en/announce/release-4.3.1.rst
Normal file
@@ -0,0 +1,29 @@
|
||||
pytest-4.3.1
|
||||
=======================================
|
||||
|
||||
pytest 4.3.1 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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Andras Mitzki
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Danilo Horta
|
||||
* Grygorii Iermolenko
|
||||
* Jeff Hale
|
||||
* Kyle Altendorf
|
||||
* Stephan Hoyer
|
||||
* Zac Hatfield-Dodds
|
||||
* Zac-HD
|
||||
* songbowen
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
39
doc/en/announce/release-4.4.0.rst
Normal file
39
doc/en/announce/release-4.4.0.rst
Normal file
@@ -0,0 +1,39 @@
|
||||
pytest-4.4.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 4.4.0 release!
|
||||
|
||||
pytest is a mature Python testing tool with more than a 2000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a number of bugs fixes and improvements, so users are encouraged
|
||||
to take a look at the CHANGELOG:
|
||||
|
||||
https://docs.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
https://docs.pytest.org/en/latest/
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* ApaDoctor
|
||||
* Bernhard M. Wiedemann
|
||||
* Brian Skinn
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Gary Tyler
|
||||
* Jeong YunWon
|
||||
* Miro Hrončok
|
||||
* Takafumi Arakaki
|
||||
* henrykironde
|
||||
* smheidrich
|
||||
|
||||
|
||||
Happy testing,
|
||||
The Pytest Development Team
|
||||
20
doc/en/announce/release-4.4.1.rst
Normal file
20
doc/en/announce/release-4.4.1.rst
Normal file
@@ -0,0 +1,20 @@
|
||||
pytest-4.4.1
|
||||
=======================================
|
||||
|
||||
pytest 4.4.1 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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
33
doc/en/announce/release-4.4.2.rst
Normal file
33
doc/en/announce/release-4.4.2.rst
Normal file
@@ -0,0 +1,33 @@
|
||||
pytest-4.4.2
|
||||
=======================================
|
||||
|
||||
pytest 4.4.2 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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Allan Lewis
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* DamianSkrzypczak
|
||||
* Daniel Hahler
|
||||
* Don Kirkby
|
||||
* Douglas Thor
|
||||
* Hugo
|
||||
* Ilya Konstantinov
|
||||
* Jon Dufresne
|
||||
* Matt Cooper
|
||||
* Nikolay Kondratyev
|
||||
* Ondřej Súkup
|
||||
* Peter Schutt
|
||||
* Romain Chossart
|
||||
* Sitaktif
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
35
doc/en/announce/release-4.5.0.rst
Normal file
35
doc/en/announce/release-4.5.0.rst
Normal file
@@ -0,0 +1,35 @@
|
||||
pytest-4.5.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 4.5.0 release!
|
||||
|
||||
pytest is a mature Python testing tool with more than a 2000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a number of bugs fixes and improvements, so users are encouraged
|
||||
to take a look at the CHANGELOG:
|
||||
|
||||
https://docs.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
https://docs.pytest.org/en/latest/
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* Floris Bruynooghe
|
||||
* Pulkit Goyal
|
||||
* Samuel Searles-Bryant
|
||||
* Zac Hatfield-Dodds
|
||||
* Zac-HD
|
||||
|
||||
|
||||
Happy testing,
|
||||
The Pytest Development Team
|
||||
43
doc/en/announce/release-4.6.0.rst
Normal file
43
doc/en/announce/release-4.6.0.rst
Normal file
@@ -0,0 +1,43 @@
|
||||
pytest-4.6.0
|
||||
=======================================
|
||||
|
||||
The pytest team is proud to announce the 4.6.0 release!
|
||||
|
||||
pytest is a mature Python testing tool with more than a 2000 tests
|
||||
against itself, passing on many different interpreters and platforms.
|
||||
|
||||
This release contains a number of bugs fixes and improvements, so users are encouraged
|
||||
to take a look at the CHANGELOG:
|
||||
|
||||
https://docs.pytest.org/en/latest/changelog.html
|
||||
|
||||
For complete documentation, please visit:
|
||||
|
||||
https://docs.pytest.org/en/latest/
|
||||
|
||||
As usual, you can upgrade from pypi via:
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Akiomi Kamakura
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
* Daniel Hahler
|
||||
* David Röthlisberger
|
||||
* Evan Kepner
|
||||
* Jeffrey Rackauckas
|
||||
* MyComputer
|
||||
* Nikita Krokosh
|
||||
* Raul Tambre
|
||||
* Thomas Hisch
|
||||
* Tim Hoffmann
|
||||
* Tomer Keren
|
||||
* Victor Maryama
|
||||
* danielx123
|
||||
* oleg-yegorov
|
||||
|
||||
|
||||
Happy testing,
|
||||
The Pytest Development Team
|
||||
19
doc/en/announce/release-4.6.1.rst
Normal file
19
doc/en/announce/release-4.6.1.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
pytest-4.6.1
|
||||
=======================================
|
||||
|
||||
pytest 4.6.1 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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
* Bruno Oliveira
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
18
doc/en/announce/release-4.6.2.rst
Normal file
18
doc/en/announce/release-4.6.2.rst
Normal file
@@ -0,0 +1,18 @@
|
||||
pytest-4.6.2
|
||||
=======================================
|
||||
|
||||
pytest 4.6.2 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/latest/changelog.html.
|
||||
|
||||
Thanks to all who contributed to this release, among them:
|
||||
|
||||
* Anthony Sottile
|
||||
|
||||
|
||||
Happy testing,
|
||||
The pytest Development Team
|
||||
@@ -12,12 +12,15 @@ Asserting with the ``assert`` statement
|
||||
|
||||
``pytest`` allows you to use the standard python ``assert`` for verifying
|
||||
expectations and values in Python tests. For example, you can write the
|
||||
following::
|
||||
following:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_assert1.py
|
||||
def f():
|
||||
return 3
|
||||
|
||||
|
||||
def test_function():
|
||||
assert f() == 4
|
||||
|
||||
@@ -30,7 +33,7 @@ you will see the return value of the function call:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_assert1.py F [100%]
|
||||
@@ -43,7 +46,7 @@ you will see the return value of the function call:
|
||||
E assert 3 == 4
|
||||
E + where 3 = f()
|
||||
|
||||
test_assert1.py:5: AssertionError
|
||||
test_assert1.py:6: AssertionError
|
||||
========================= 1 failed in 0.12 seconds =========================
|
||||
|
||||
``pytest`` has support for showing the values of the most common subexpressions
|
||||
@@ -52,7 +55,9 @@ operators. (See :ref:`tbreportdemo`). This allows you to use the
|
||||
idiomatic python constructs without boilerplate code while not losing
|
||||
introspection information.
|
||||
|
||||
However, if you specify a message with the assertion like this::
|
||||
However, if you specify a message with the assertion like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
assert a % 2 == 0, "value was odd, should be even"
|
||||
|
||||
@@ -67,22 +72,29 @@ Assertions about expected exceptions
|
||||
------------------------------------------
|
||||
|
||||
In order to write assertions about raised exceptions, you can use
|
||||
``pytest.raises`` as a context manager like this::
|
||||
``pytest.raises`` as a context manager like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_zero_division():
|
||||
with pytest.raises(ZeroDivisionError):
|
||||
1 / 0
|
||||
|
||||
and if you need to have access to the actual exception info you may use::
|
||||
and if you need to have access to the actual exception info you may use:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_recursion_depth():
|
||||
with pytest.raises(RuntimeError) as excinfo:
|
||||
|
||||
def f():
|
||||
f()
|
||||
|
||||
f()
|
||||
assert 'maximum recursion' in str(excinfo.value)
|
||||
assert "maximum recursion" in str(excinfo.value)
|
||||
|
||||
``excinfo`` is a ``ExceptionInfo`` instance, which is a wrapper around
|
||||
the actual exception raised. The main attributes of interest are
|
||||
@@ -90,15 +102,19 @@ the actual exception raised. The main attributes of interest are
|
||||
|
||||
You can pass a ``match`` keyword parameter to the context-manager to test
|
||||
that a regular expression matches on the string representation of an exception
|
||||
(similar to the ``TestCase.assertRaisesRegexp`` method from ``unittest``)::
|
||||
(similar to the ``TestCase.assertRaisesRegexp`` method from ``unittest``):
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def myfunc():
|
||||
raise ValueError("Exception 123 raised")
|
||||
|
||||
|
||||
def test_match():
|
||||
with pytest.raises(ValueError, match=r'.* 123 .*'):
|
||||
with pytest.raises(ValueError, match=r".* 123 .*"):
|
||||
myfunc()
|
||||
|
||||
The regexp parameter of the ``match`` method is matched with the ``re.search``
|
||||
@@ -107,7 +123,9 @@ well.
|
||||
|
||||
There's an alternate form of the ``pytest.raises`` function where you pass
|
||||
a function that will be executed with the given ``*args`` and ``**kwargs`` and
|
||||
assert that the given exception is raised::
|
||||
assert that the given exception is raised:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pytest.raises(ExpectedException, func, *args, **kwargs)
|
||||
|
||||
@@ -116,7 +134,9 @@ exception* or *wrong exception*.
|
||||
|
||||
Note that it is also possible to specify a "raises" argument to
|
||||
``pytest.mark.xfail``, which checks that the test is failing in a more
|
||||
specific way than just having any exception raised::
|
||||
specific way than just having any exception raised:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.xfail(raises=IndexError)
|
||||
def test_f():
|
||||
@@ -134,7 +154,7 @@ or bugs in dependencies.
|
||||
Assertions about expected warnings
|
||||
-----------------------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
You can check that code raises a particular warning using
|
||||
:ref:`pytest.warns <warns>`.
|
||||
@@ -145,13 +165,16 @@ You can check that code raises a particular warning using
|
||||
Making use of context-sensitive comparisons
|
||||
-------------------------------------------------
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
|
||||
``pytest`` has rich support for providing context-sensitive information
|
||||
when it encounters comparisons. For example::
|
||||
when it encounters comparisons. For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_assert2.py
|
||||
|
||||
|
||||
def test_set_comparison():
|
||||
set1 = set("1308")
|
||||
set2 = set("8035")
|
||||
@@ -165,7 +188,7 @@ if you run this module:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_assert2.py F [100%]
|
||||
@@ -184,7 +207,7 @@ if you run this module:
|
||||
E '5'
|
||||
E Use -v to get the full diff
|
||||
|
||||
test_assert2.py:5: AssertionError
|
||||
test_assert2.py:6: AssertionError
|
||||
========================= 1 failed in 0.12 seconds =========================
|
||||
|
||||
Special comparisons are done for a number of cases:
|
||||
@@ -205,16 +228,21 @@ the ``pytest_assertrepr_compare`` hook.
|
||||
:noindex:
|
||||
|
||||
As an example consider adding the following hook in a :ref:`conftest.py <conftest.py>`
|
||||
file which provides an alternative explanation for ``Foo`` objects::
|
||||
file which provides an alternative explanation for ``Foo`` objects:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
from test_foocompare import Foo
|
||||
|
||||
|
||||
def pytest_assertrepr_compare(op, left, right):
|
||||
if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
|
||||
return ['Comparing Foo instances:',
|
||||
' vals: %s != %s' % (left.val, right.val)]
|
||||
return ["Comparing Foo instances:", " vals: %s != %s" % (left.val, right.val)]
|
||||
|
||||
now, given this test module::
|
||||
now, given this test module:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_foocompare.py
|
||||
class Foo(object):
|
||||
@@ -224,6 +252,7 @@ now, given this test module::
|
||||
def __eq__(self, other):
|
||||
return self.val == other.val
|
||||
|
||||
|
||||
def test_compare():
|
||||
f1 = Foo(1)
|
||||
f2 = Foo(2)
|
||||
@@ -246,16 +275,16 @@ the conftest file:
|
||||
E assert Comparing Foo instances:
|
||||
E vals: 1 != 2
|
||||
|
||||
test_foocompare.py:11: AssertionError
|
||||
test_foocompare.py:12: AssertionError
|
||||
1 failed in 0.12 seconds
|
||||
|
||||
.. _assert-details:
|
||||
.. _`assert introspection`:
|
||||
|
||||
Advanced assertion introspection
|
||||
----------------------------------
|
||||
Assertion introspection details
|
||||
-------------------------------
|
||||
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
|
||||
Reporting details about a failing assertion is achieved by rewriting assert
|
||||
@@ -266,35 +295,53 @@ supporting modules which are not themselves test modules will not be rewritten**
|
||||
|
||||
You can manually enable assertion rewriting for an imported module by calling
|
||||
`register_assert_rewrite <https://docs.pytest.org/en/latest/writing_plugins.html#assertion-rewriting>`_
|
||||
before you import it (a good place to do that is in ``conftest.py``).
|
||||
|
||||
.. note::
|
||||
|
||||
``pytest`` rewrites test modules on import by using an import
|
||||
hook to write new ``pyc`` files. Most of the time this works transparently.
|
||||
However, if you are messing with import yourself, the import hook may
|
||||
interfere.
|
||||
|
||||
If this is the case you have two options:
|
||||
|
||||
* Disable rewriting for a specific module by adding the string
|
||||
``PYTEST_DONT_REWRITE`` to its docstring.
|
||||
|
||||
* Disable rewriting for all modules by using ``--assert=plain``.
|
||||
|
||||
Additionally, rewriting will fail silently if it cannot write new ``.pyc`` files,
|
||||
i.e. in a read-only filesystem or a zipfile.
|
||||
|
||||
before you import it (a good place to do that is in your root ``conftest.py``).
|
||||
|
||||
For further information, Benjamin Peterson wrote up `Behind the scenes of pytest's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
Assertion rewriting caches files on disk
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``pytest`` will write back the rewritten modules to disk for caching. You can disable
|
||||
this behavior (for example to avoid leaving stale ``.pyc`` files around in projects that
|
||||
move files around a lot) by adding this to the top of your ``conftest.py`` file:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
Note that you still get the benefits of assertion introspection, the only change is that
|
||||
the ``.pyc`` files won't be cached on disk.
|
||||
|
||||
Additionally, rewriting will silently skip caching if it cannot write new ``.pyc`` files,
|
||||
i.e. in a read-only filesystem or a zipfile.
|
||||
|
||||
|
||||
Disabling assert rewriting
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
``pytest`` rewrites test modules on import by using an import
|
||||
hook to write new ``pyc`` files. Most of the time this works transparently.
|
||||
However, if you are working with the import machinery yourself, the import hook may
|
||||
interfere.
|
||||
|
||||
If this is the case you have two options:
|
||||
|
||||
* Disable rewriting for a specific module by adding the string
|
||||
``PYTEST_DONT_REWRITE`` to its docstring.
|
||||
|
||||
* Disable rewriting for all modules by using ``--assert=plain``.
|
||||
|
||||
|
||||
|
||||
Add assert rewriting as an alternate introspection technique.
|
||||
|
||||
.. versionchanged:: 2.1
|
||||
|
||||
Introduce the ``--assert`` option. Deprecate ``--no-assert`` and
|
||||
``--nomagic``.
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
Removes the ``--no-assert`` and ``--nomagic`` options.
|
||||
Removes the ``--assert=reinterp`` option.
|
||||
|
||||
@@ -8,18 +8,26 @@ When using bash as your shell, ``pytest`` can use argcomplete
|
||||
(https://argcomplete.readthedocs.io/) for auto-completion.
|
||||
For this ``argcomplete`` needs to be installed **and** enabled.
|
||||
|
||||
Install argcomplete using::
|
||||
Install argcomplete using:
|
||||
|
||||
sudo pip install 'argcomplete>=0.5.7'
|
||||
.. code-block:: bash
|
||||
|
||||
For global activation of all argcomplete enabled python applications run::
|
||||
sudo pip install 'argcomplete>=0.5.7'
|
||||
|
||||
For global activation of all argcomplete enabled python applications run:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sudo activate-global-python-argcomplete
|
||||
|
||||
For permanent (but not global) ``pytest`` activation, use::
|
||||
For permanent (but not global) ``pytest`` activation, use:
|
||||
|
||||
register-python-argcomplete pytest >> ~/.bashrc
|
||||
.. code-block:: bash
|
||||
|
||||
For one-time activation of argcomplete for ``pytest`` only, use::
|
||||
register-python-argcomplete pytest >> ~/.bashrc
|
||||
|
||||
eval "$(register-python-argcomplete pytest)"
|
||||
For one-time activation of argcomplete for ``pytest`` only, use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
eval "$(register-python-argcomplete pytest)"
|
||||
|
||||
@@ -27,36 +27,47 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
name of your plugin or application to avoid clashes with other cache users.
|
||||
|
||||
Values can be any object handled by the json stdlib module.
|
||||
|
||||
capsys
|
||||
Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
which return a ``(out, err)`` namedtuple. ``out`` and ``err`` will be ``text``
|
||||
objects.
|
||||
Enable text capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||
|
||||
The captured output is made available via ``capsys.readouterr()`` method
|
||||
calls, which return a ``(out, err)`` namedtuple.
|
||||
``out`` and ``err`` will be ``text`` objects.
|
||||
|
||||
capsysbinary
|
||||
Enable capturing of writes to ``sys.stdout`` and ``sys.stderr`` and make
|
||||
captured output available via ``capsys.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``bytes``
|
||||
objects.
|
||||
Enable bytes capturing of writes to ``sys.stdout`` and ``sys.stderr``.
|
||||
|
||||
The captured output is made available via ``capsysbinary.readouterr()``
|
||||
method calls, which return a ``(out, err)`` namedtuple.
|
||||
``out`` and ``err`` will be ``bytes`` objects.
|
||||
|
||||
capfd
|
||||
Enable capturing of writes to file descriptors ``1`` and ``2`` and make
|
||||
captured output available via ``capfd.readouterr()`` method calls
|
||||
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be ``text``
|
||||
objects.
|
||||
Enable text capturing of writes to file descriptors ``1`` and ``2``.
|
||||
|
||||
The captured output is made available via ``capfd.readouterr()`` method
|
||||
calls, which return a ``(out, err)`` namedtuple.
|
||||
``out`` and ``err`` will be ``text`` objects.
|
||||
|
||||
capfdbinary
|
||||
Enable capturing of write to file descriptors 1 and 2 and make
|
||||
captured output available via ``capfdbinary.readouterr`` method calls
|
||||
which return a ``(out, err)`` tuple. ``out`` and ``err`` will be
|
||||
``bytes`` objects.
|
||||
doctest_namespace
|
||||
Enable bytes capturing of writes to file descriptors ``1`` and ``2``.
|
||||
|
||||
The captured output is made available via ``capfd.readouterr()`` method
|
||||
calls, which return a ``(out, err)`` namedtuple.
|
||||
``out`` and ``err`` will be ``byte`` objects.
|
||||
|
||||
doctest_namespace [session scope]
|
||||
Fixture that returns a :py:class:`dict` that will be injected into the namespace of doctests.
|
||||
pytestconfig
|
||||
|
||||
pytestconfig [session scope]
|
||||
Session-scoped fixture that returns the :class:`_pytest.config.Config` object.
|
||||
|
||||
Example::
|
||||
|
||||
def test_foo(pytestconfig):
|
||||
if pytestconfig.getoption("verbose"):
|
||||
if pytestconfig.getoption("verbose") > 0:
|
||||
...
|
||||
|
||||
record_property
|
||||
Add an extra properties the calling test.
|
||||
User properties become part of the test report and are available to the
|
||||
@@ -68,10 +79,26 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
|
||||
def test_function(record_property):
|
||||
record_property("example_key", 1)
|
||||
|
||||
record_xml_attribute
|
||||
Add extra xml attributes to the tag for the calling test.
|
||||
The fixture is callable with ``(name, value)``, with value being
|
||||
automatically xml-encoded
|
||||
|
||||
record_testsuite_property [session scope]
|
||||
Records a new ``<property>`` tag as child of the root ``<testsuite>``. This is suitable to
|
||||
writing global information regarding the entire test suite, and is compatible with ``xunit2`` JUnit family.
|
||||
|
||||
This is a ``session``-scoped fixture which is called with ``(name, value)``. Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_foo(record_testsuite_property):
|
||||
record_testsuite_property("ARCH", "PPC")
|
||||
record_testsuite_property("STORAGE_TYPE", "CEPH")
|
||||
|
||||
``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped.
|
||||
|
||||
caplog
|
||||
Access and control log capturing.
|
||||
|
||||
@@ -81,6 +108,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
* caplog.records -> list of logging.LogRecord instances
|
||||
* caplog.record_tuples -> list of (logger_name, level, message) tuples
|
||||
* caplog.clear() -> clear captured records and formatted log output string
|
||||
|
||||
monkeypatch
|
||||
The returned ``monkeypatch`` fixture provides these
|
||||
helper methods to modify objects, dictionaries or os.environ::
|
||||
@@ -98,15 +126,19 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
test function or fixture has finished. The ``raising``
|
||||
parameter determines if a KeyError or AttributeError
|
||||
will be raised if the set/deletion operation has no target.
|
||||
|
||||
recwarn
|
||||
Return a :class:`WarningsRecorder` instance that records all warnings emitted by test functions.
|
||||
|
||||
See http://docs.python.org/library/warnings.html for information
|
||||
on warning categories.
|
||||
tmpdir_factory
|
||||
|
||||
tmpdir_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempdirFactory` instance for the test session.
|
||||
tmp_path_factory
|
||||
|
||||
tmp_path_factory [session scope]
|
||||
Return a :class:`_pytest.tmpdir.TempPathFactory` instance for the test session.
|
||||
|
||||
tmpdir
|
||||
Return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
@@ -115,6 +147,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
path object.
|
||||
|
||||
.. _`py.path.local`: https://py.readthedocs.io/en/latest/path.html
|
||||
|
||||
tmp_path
|
||||
Return a temporary directory path object
|
||||
which is unique to each test function invocation,
|
||||
@@ -126,6 +159,7 @@ For information about fixtures, see :ref:`fixtures`. To see a complete list of a
|
||||
|
||||
in python < 3.6 this is a pathlib2.Path
|
||||
|
||||
|
||||
no tests ran in 0.12 seconds
|
||||
|
||||
You can also interactively ask for help, e.g. by typing on the Python interactive prompt something like::
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Cache: working with cross-testrun state
|
||||
=======================================
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
Usage
|
||||
---------
|
||||
@@ -82,7 +82,7 @@ If you then run it with ``--lf``:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 50 items / 48 deselected / 2 selected
|
||||
run-last-failure: rerun previous 2 failures
|
||||
|
||||
@@ -126,7 +126,7 @@ of ``FF`` and dots):
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 50 items
|
||||
run-last-failure: rerun previous 2 failures first
|
||||
|
||||
@@ -168,7 +168,9 @@ Behavior when no tests failed in the last run
|
||||
|
||||
When no tests failed in the last run, or when no cached ``lastfailed`` data was
|
||||
found, ``pytest`` can be configured either to run all of the tests or no tests,
|
||||
using the ``--last-failed-no-failures`` option, which takes one of the following values::
|
||||
using the ``--last-failed-no-failures`` option, which takes one of the following values:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --last-failed --last-failed-no-failures all # run all tests (default behavior)
|
||||
pytest --last-failed --last-failed-no-failures none # run no tests and exit
|
||||
@@ -216,8 +218,6 @@ If you run this command for the first time, you can see the print statement:
|
||||
def test_function(mydata):
|
||||
> assert mydata == 23
|
||||
E assert 42 == 23
|
||||
E -42
|
||||
E +23
|
||||
|
||||
test_caching.py:17: AssertionError
|
||||
-------------------------- Captured stdout setup ---------------------------
|
||||
@@ -239,8 +239,6 @@ the cache and nothing will be printed:
|
||||
def test_function(mydata):
|
||||
> assert mydata == 23
|
||||
E assert 42 == 23
|
||||
E -42
|
||||
E +23
|
||||
|
||||
test_caching.py:17: AssertionError
|
||||
1 failed in 0.12 seconds
|
||||
@@ -249,7 +247,7 @@ See the :ref:`cache-api` for more details.
|
||||
|
||||
|
||||
Inspecting Cache content
|
||||
-------------------------------
|
||||
------------------------
|
||||
|
||||
You can always peek at the content of the cache using the
|
||||
``--cache-show`` command line option:
|
||||
@@ -260,9 +258,9 @@ You can always peek at the content of the cache using the
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
------------------------------- cache values -------------------------------
|
||||
--------------------------- cache values for '*' ---------------------------
|
||||
cache/lastfailed contains:
|
||||
{'test_50.py::test_num[17]': True,
|
||||
'test_50.py::test_num[25]': True,
|
||||
@@ -279,11 +277,30 @@ You can always peek at the content of the cache using the
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
|
||||
``--cache-show`` takes an optional argument to specify a glob pattern for
|
||||
filtering:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --cache-show example/*
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
----------------------- cache values for 'example/*' -----------------------
|
||||
example/value contains:
|
||||
42
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
|
||||
Clearing Cache content
|
||||
-------------------------------
|
||||
----------------------
|
||||
|
||||
You can instruct pytest to clear all cache files and values
|
||||
by adding the ``--cache-clear`` option like this::
|
||||
by adding the ``--cache-clear`` option like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --cache-clear
|
||||
|
||||
|
||||
@@ -35,7 +35,9 @@ There are two ways in which ``pytest`` can perform capturing:
|
||||
|
||||
.. _`disable capturing`:
|
||||
|
||||
You can influence output capturing mechanisms from the command line::
|
||||
You can influence output capturing mechanisms from the command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -s # disable all capturing
|
||||
pytest --capture=sys # replace sys.stdout/stderr with in-mem files
|
||||
@@ -69,7 +71,7 @@ of the failing function and hide the other one:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py .F [100%]
|
||||
@@ -119,11 +121,11 @@ same interface but allows to also capture output from
|
||||
libraries or subprocesses that directly write to operating
|
||||
system level output streams (FD1 and FD2).
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
The return value from ``readouterr`` changed to a ``namedtuple`` with two attributes, ``out`` and ``err``.
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
If the code under test writes non-textual data, you can capture this using
|
||||
the ``capsysbinary`` fixture which instead returns ``bytes`` from
|
||||
@@ -131,7 +133,7 @@ the ``readouterr`` method. The ``capfsysbinary`` fixture is currently only
|
||||
available in python 3.
|
||||
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
If the code under test writes non-textual data, you can capture this using
|
||||
the ``capfdbinary`` fixture which instead returns ``bytes`` from
|
||||
@@ -139,7 +141,7 @@ the ``readouterr`` method. The ``capfdbinary`` fixture operates on the
|
||||
filedescriptor level.
|
||||
|
||||
|
||||
.. versionadded:: 3.0
|
||||
|
||||
|
||||
To temporarily disable capture within a test, both ``capsys``
|
||||
and ``capfd`` have a ``disabled()`` method that can be used
|
||||
|
||||
@@ -335,7 +335,7 @@ intersphinx_mapping = {"python": ("https://docs.python.org/3", None)}
|
||||
def setup(app):
|
||||
# from sphinx.ext.autodoc import cut_lines
|
||||
# app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||
app.add_description_unit(
|
||||
app.add_object_type(
|
||||
"confval",
|
||||
"confval",
|
||||
objname="configuration value",
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
collect_ignore = ["conf.py"]
|
||||
|
||||
@@ -50,6 +50,7 @@ Full pytest documentation
|
||||
projects
|
||||
faq
|
||||
contact
|
||||
tidelift
|
||||
|
||||
.. only:: html
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@ Command line options and configuration file settings
|
||||
-----------------------------------------------------------------
|
||||
|
||||
You can get help on command line options and values in INI-style
|
||||
configurations files by using the general help option::
|
||||
configurations files by using the general help option:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -h # prints options _and_ config file settings
|
||||
|
||||
@@ -18,7 +20,7 @@ which were registered by installed plugins.
|
||||
Initialization: determining rootdir and inifile
|
||||
-----------------------------------------------
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
pytest determines a ``rootdir`` for each test run which depends on
|
||||
the command line arguments (specified test files, paths) and on
|
||||
@@ -88,16 +90,20 @@ The ``config`` object will subsequently carry these attributes:
|
||||
|
||||
- ``config.inifile``: the determined ini-file, may be ``None``.
|
||||
|
||||
The rootdir is used a reference directory for constructing test
|
||||
The rootdir is used as a reference directory for constructing test
|
||||
addresses ("nodeids") and can be used also by plugins for storing
|
||||
per-testrun information.
|
||||
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest path/to/testdir path/other/
|
||||
|
||||
will determine the common ancestor as ``path`` and then
|
||||
check for ini-files as follows::
|
||||
check for ini-files as follows:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
# first look for pytest.ini files
|
||||
path/pytest.ini
|
||||
@@ -127,25 +133,33 @@ progress output, you can write it into a configuration file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
# (or tox.ini or setup.cfg)
|
||||
# content of pytest.ini or tox.ini
|
||||
# setup.cfg files should use [tool:pytest] section instead
|
||||
[pytest]
|
||||
addopts = -ra -q
|
||||
|
||||
Alternatively, you can set a ``PYTEST_ADDOPTS`` environment variable to add command
|
||||
line options while the environment is in use::
|
||||
line options while the environment is in use:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
export PYTEST_ADDOPTS="-v"
|
||||
|
||||
Here's how the command-line is built in the presence of ``addopts`` or the environment variable::
|
||||
Here's how the command-line is built in the presence of ``addopts`` or the environment variable:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
<pytest.ini:addopts> $PYTEST_ADDOPTS <extra command-line arguments>
|
||||
|
||||
So if the user executes in the command-line::
|
||||
So if the user executes in the command-line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -m slow
|
||||
|
||||
The actual command line executed is::
|
||||
The actual command line executed is:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -ra -q -v -m slow
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ Below is a complete list of all pytest features which are considered deprecated.
|
||||
:class:`_pytest.warning_types.PytestWarning` or subclasses, which can be filtered using
|
||||
:ref:`standard warning filters <warnings>`.
|
||||
|
||||
.. _`raises message deprecated`:
|
||||
|
||||
``"message"`` parameter of ``pytest.raises``
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -60,7 +62,8 @@ If you still have concerns about this deprecation and future removal, please com
|
||||
|
||||
The ``pytest.config`` global object is deprecated. Instead use
|
||||
``request.config`` (via the ``request`` fixture) or if you are a plugin author
|
||||
use the ``pytest_configure(config)`` hook.
|
||||
use the ``pytest_configure(config)`` hook. Note that many hooks can also access
|
||||
the ``config`` object indirectly, through ``session.config`` or ``item.config`` for example.
|
||||
|
||||
.. _raises-warns-exec:
|
||||
|
||||
@@ -104,7 +107,7 @@ Becomes:
|
||||
Result log (``--result-log``)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
|
||||
The ``--resultlog`` command line option has been deprecated: it is little used
|
||||
and there are more modern and better alternatives, for example `pytest-tap <https://tappy.readthedocs.io/en/latest/>`_.
|
||||
|
||||
@@ -4,31 +4,69 @@ Doctest integration for modules and test files
|
||||
|
||||
By default all files matching the ``test*.txt`` pattern will
|
||||
be run through the python standard ``doctest`` module. You
|
||||
can change the pattern by issuing::
|
||||
can change the pattern by issuing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --doctest-glob='*.rst'
|
||||
|
||||
on the command line. Since version ``2.9``, ``--doctest-glob``
|
||||
can be given multiple times in the command-line.
|
||||
on the command line. ``--doctest-glob`` can be given multiple times in the command-line.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
If you then have a text file like this:
|
||||
|
||||
You can specify the encoding that will be used for those doctest files
|
||||
using the ``doctest_encoding`` ini option:
|
||||
.. code-block:: text
|
||||
|
||||
.. code-block:: ini
|
||||
# content of test_example.txt
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
doctest_encoding = latin1
|
||||
hello this is a doctest
|
||||
>>> x = 3
|
||||
>>> x
|
||||
3
|
||||
|
||||
The default encoding is UTF-8.
|
||||
then you can just invoke ``pytest`` directly:
|
||||
|
||||
You can also trigger running of doctests
|
||||
from docstrings in all python modules (including regular
|
||||
python test modules)::
|
||||
.. code-block:: pytest
|
||||
|
||||
pytest --doctest-modules
|
||||
$ pytest
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_example.txt . [100%]
|
||||
|
||||
========================= 1 passed in 0.12 seconds =========================
|
||||
|
||||
By default, pytest will collect ``test*.txt`` files looking for doctest directives, but you
|
||||
can pass additional globs using the ``--doctest-glob`` option (multi-allowed).
|
||||
|
||||
In addition to text files, you can also execute doctests directly from docstrings of your classes
|
||||
and functions, including from test modules:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of mymodule.py
|
||||
def something():
|
||||
""" a doctest in a docstring
|
||||
>>> something()
|
||||
42
|
||||
"""
|
||||
return 42
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pytest --doctest-modules
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
mymodule.py . [ 50%]
|
||||
test_example.txt . [100%]
|
||||
|
||||
========================= 2 passed in 0.12 seconds =========================
|
||||
|
||||
You can make these changes permanent in your project by
|
||||
putting them into a pytest.ini file like this:
|
||||
@@ -39,53 +77,37 @@ putting them into a pytest.ini file like this:
|
||||
[pytest]
|
||||
addopts = --doctest-modules
|
||||
|
||||
If you then have a text file like this::
|
||||
.. note::
|
||||
|
||||
# content of example.rst
|
||||
The builtin pytest doctest supports only ``doctest`` blocks, but if you are looking
|
||||
for more advanced checking over *all* your documentation,
|
||||
including doctests, ``.. codeblock:: python`` Sphinx directive support,
|
||||
and any other examples your documentation may include, you may wish to
|
||||
consider `Sybil <https://sybil.readthedocs.io/en/latest/index.html>`__.
|
||||
It provides pytest integration out of the box.
|
||||
|
||||
hello this is a doctest
|
||||
>>> x = 3
|
||||
>>> x
|
||||
3
|
||||
|
||||
and another like this::
|
||||
Encoding
|
||||
--------
|
||||
|
||||
# content of mymodule.py
|
||||
def something():
|
||||
""" a doctest in a docstring
|
||||
>>> something()
|
||||
42
|
||||
"""
|
||||
return 42
|
||||
The default encoding is **UTF-8**, but you can specify the encoding
|
||||
that will be used for those doctest files using the
|
||||
``doctest_encoding`` ini option:
|
||||
|
||||
then you can just invoke ``pytest`` without command line options:
|
||||
.. code-block:: ini
|
||||
|
||||
.. code-block:: pytest
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
doctest_encoding = latin1
|
||||
|
||||
$ pytest
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile: pytest.ini
|
||||
collected 1 item
|
||||
Using 'doctest' options
|
||||
-----------------------
|
||||
|
||||
mymodule.py . [100%]
|
||||
The standard ``doctest`` module provides some `options <https://docs.python.org/3/library/doctest.html#option-flags>`__
|
||||
to configure the strictness of doctest tests. In pytest, you can enable those flags using the
|
||||
configuration file.
|
||||
|
||||
========================= 1 passed in 0.12 seconds =========================
|
||||
|
||||
It is possible to use fixtures using the ``getfixture`` helper::
|
||||
|
||||
# content of example.rst
|
||||
>>> tmp = getfixture('tmpdir')
|
||||
>>> ...
|
||||
>>>
|
||||
|
||||
Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
|
||||
when executing text doctest files.
|
||||
|
||||
The standard ``doctest`` module provides some setting flags to configure the
|
||||
strictness of doctest tests. In pytest, you can enable those flags using the
|
||||
configuration file. To make pytest ignore trailing whitespaces and ignore
|
||||
For example, to make pytest ignore trailing whitespaces and ignore
|
||||
lengthy exception stack traces you can just write:
|
||||
|
||||
.. code-block:: ini
|
||||
@@ -102,34 +124,67 @@ Python 3 unchanged:
|
||||
* ``ALLOW_BYTES``: when enabled, the ``b`` prefix is stripped from byte strings
|
||||
in expected doctest output.
|
||||
|
||||
As with any other option flag, these flags can be enabled in ``pytest.ini`` using
|
||||
the ``doctest_optionflags`` ini option:
|
||||
Alternatively, options can be enabled by an inline comment in the doc test
|
||||
itself:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
doctest_optionflags = ALLOW_UNICODE ALLOW_BYTES
|
||||
|
||||
|
||||
Alternatively, it can be enabled by an inline comment in the doc test
|
||||
itself::
|
||||
.. code-block:: rst
|
||||
|
||||
# content of example.rst
|
||||
>>> get_unicode_greeting() # doctest: +ALLOW_UNICODE
|
||||
'Hello'
|
||||
|
||||
By default, pytest would report only the first failure for a given doctest. If
|
||||
you want to continue the test even when you have failures, do::
|
||||
By default, pytest would report only the first failure for a given doctest. If
|
||||
you want to continue the test even when you have failures, do:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --doctest-modules --doctest-continue-on-failure
|
||||
|
||||
|
||||
Output format
|
||||
-------------
|
||||
|
||||
You can change the diff output format on failure for your doctests
|
||||
by using one of standard doctest modules format in options
|
||||
(see :data:`python:doctest.REPORT_UDIFF`, :data:`python:doctest.REPORT_CDIFF`,
|
||||
:data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`):
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --doctest-modules --doctest-report none
|
||||
pytest --doctest-modules --doctest-report udiff
|
||||
pytest --doctest-modules --doctest-report cdiff
|
||||
pytest --doctest-modules --doctest-report ndiff
|
||||
pytest --doctest-modules --doctest-report only_first_failure
|
||||
|
||||
|
||||
pytest-specific features
|
||||
------------------------
|
||||
|
||||
Some features are provided to make writing doctests easier or with better integration with
|
||||
your existing test suite. Keep in mind however that by using those features you will make
|
||||
your doctests incompatible with the standard ``doctests`` module.
|
||||
|
||||
Using fixtures
|
||||
^^^^^^^^^^^^^^
|
||||
|
||||
It is possible to use fixtures using the ``getfixture`` helper:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
# content of example.rst
|
||||
>>> tmp = getfixture('tmpdir')
|
||||
>>> ...
|
||||
>>>
|
||||
|
||||
Also, :ref:`usefixtures` and :ref:`autouse` fixtures are supported
|
||||
when executing text doctest files.
|
||||
|
||||
|
||||
.. _`doctest_namespace`:
|
||||
|
||||
The 'doctest_namespace' fixture
|
||||
-------------------------------
|
||||
|
||||
.. versionadded:: 3.0
|
||||
'doctest_namespace' fixture
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The ``doctest_namespace`` fixture can be used to inject items into the
|
||||
namespace in which your doctests run. It is intended to be used within
|
||||
@@ -159,18 +214,14 @@ Note that like the normal ``conftest.py``, the fixtures are discovered in the di
|
||||
Meaning that if you put your doctest with your source code, the relevant conftest.py needs to be in the same directory tree.
|
||||
Fixtures will not be discovered in a sibling directory tree!
|
||||
|
||||
Output format
|
||||
-------------
|
||||
Skipping tests dynamically
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.0
|
||||
.. versionadded:: 4.4
|
||||
|
||||
You can change the diff output format on failure for your doctests
|
||||
by using one of standard doctest modules format in options
|
||||
(see :data:`python:doctest.REPORT_UDIFF`, :data:`python:doctest.REPORT_CDIFF`,
|
||||
:data:`python:doctest.REPORT_NDIFF`, :data:`python:doctest.REPORT_ONLY_FIRST_FAILURE`)::
|
||||
You can use ``pytest.skip`` to dynamically skip doctests. For example::
|
||||
|
||||
pytest --doctest-modules --doctest-report none
|
||||
pytest --doctest-modules --doctest-report udiff
|
||||
pytest --doctest-modules --doctest-report cdiff
|
||||
pytest --doctest-modules --doctest-report ndiff
|
||||
pytest --doctest-modules --doctest-report only_first_failure
|
||||
>>> import sys, pytest
|
||||
>>> if sys.platform.startswith('win'):
|
||||
... pytest.skip('this doctest does not work on Windows')
|
||||
...
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import six
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
import _pytest._code
|
||||
import pytest
|
||||
from pytest import raises
|
||||
@@ -199,7 +198,7 @@ def test_dynamic_compile_shows_nicely():
|
||||
name = "abc-123"
|
||||
module = imp.new_module(name)
|
||||
code = _pytest._code.compile(src, name, "exec")
|
||||
six.exec_(code, module.__dict__)
|
||||
exec(code, module.__dict__)
|
||||
sys.modules[name] = module
|
||||
module.foo()
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import py
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
hello = "world"
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import py
|
||||
|
||||
failure_demo = py.path.local(__file__).dirpath("failure_demo.py")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
def setup_module(module):
|
||||
module.TestStateFullThing.classcount = 0
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
collect_ignore = ["nonpython"]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
def test_quick(setup):
|
||||
pass
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
def test_something(setup):
|
||||
assert setup.timecostly == 1
|
||||
|
||||
|
||||
@@ -4,28 +4,40 @@
|
||||
Working with custom markers
|
||||
=================================================
|
||||
|
||||
Here are some example using the :ref:`mark` mechanism.
|
||||
Here are some examples using the :ref:`mark` mechanism.
|
||||
|
||||
.. _`mark run`:
|
||||
|
||||
Marking test functions and selecting them for a run
|
||||
----------------------------------------------------
|
||||
|
||||
You can "mark" a test function with custom metadata like this::
|
||||
You can "mark" a test function with custom metadata like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_server.py
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.webtest
|
||||
def test_send_http():
|
||||
pass # perform some webtest test for your app
|
||||
pass # perform some webtest test for your app
|
||||
|
||||
|
||||
def test_something_quick():
|
||||
pass
|
||||
|
||||
|
||||
def test_another():
|
||||
pass
|
||||
|
||||
|
||||
class TestClass(object):
|
||||
def test_method(self):
|
||||
pass
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
You can then restrict a test run to only run tests marked with ``webtest``:
|
||||
|
||||
@@ -35,7 +47,7 @@ You can then restrict a test run to only run tests marked with ``webtest``:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 4 items / 3 deselected / 1 selected
|
||||
|
||||
test_server.py::test_send_http PASSED [100%]
|
||||
@@ -50,7 +62,7 @@ Or the inverse, running all tests except the webtest ones:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 4 items / 1 deselected / 3 selected
|
||||
|
||||
test_server.py::test_something_quick PASSED [ 33%]
|
||||
@@ -72,7 +84,7 @@ tests based on their module, class, method, or function name:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 1 item
|
||||
|
||||
test_server.py::TestClass::test_method PASSED [100%]
|
||||
@@ -87,7 +99,7 @@ You can also select on the class:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 1 item
|
||||
|
||||
test_server.py::TestClass::test_method PASSED [100%]
|
||||
@@ -102,7 +114,7 @@ Or select multiple nodes:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_server.py::TestClass::test_method PASSED [ 50%]
|
||||
@@ -142,7 +154,7 @@ select tests based on their names:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 4 items / 3 deselected / 1 selected
|
||||
|
||||
test_server.py::test_send_http PASSED [100%]
|
||||
@@ -157,7 +169,7 @@ And you can also run all tests except the ones that match the keyword:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 4 items / 1 deselected / 3 selected
|
||||
|
||||
test_server.py::test_something_quick PASSED [ 33%]
|
||||
@@ -174,7 +186,7 @@ Or to select "http" and "quick" tests:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 4 items / 2 deselected / 2 selected
|
||||
|
||||
test_server.py::test_send_http PASSED [ 50%]
|
||||
@@ -200,18 +212,22 @@ Or to select "http" and "quick" tests:
|
||||
Registering markers
|
||||
-------------------------------------
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
|
||||
.. ini-syntax for custom markers:
|
||||
|
||||
Registering markers for your test suite is simple::
|
||||
Registering markers for your test suite is simple:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
markers =
|
||||
webtest: mark a test as a webtest.
|
||||
|
||||
You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
|
||||
You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --markers
|
||||
@pytest.mark.webtest: mark a test as a webtest.
|
||||
@@ -245,7 +261,7 @@ For an example on how to add and work with markers from a plugin, see
|
||||
* Asking for existing markers via ``pytest --markers`` gives good output
|
||||
|
||||
* Typos in function markers are treated as an error if you use
|
||||
the ``--strict`` option.
|
||||
the ``--strict-markers`` option.
|
||||
|
||||
.. _`scoped-marking`:
|
||||
|
||||
@@ -253,14 +269,19 @@ Marking whole classes or modules
|
||||
----------------------------------------------------
|
||||
|
||||
You may use ``pytest.mark`` decorators with classes to apply markers to all of
|
||||
its test methods::
|
||||
its test methods:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_mark_classlevel.py
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.webtest
|
||||
class TestClass(object):
|
||||
def test_startup(self):
|
||||
pass
|
||||
|
||||
def test_startup_and_more(self):
|
||||
pass
|
||||
|
||||
@@ -268,17 +289,23 @@ This is equivalent to directly applying the decorator to the
|
||||
two test functions.
|
||||
|
||||
To remain backward-compatible with Python 2.4 you can also set a
|
||||
``pytestmark`` attribute on a TestClass like this::
|
||||
``pytestmark`` attribute on a TestClass like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestClass(object):
|
||||
pytestmark = pytest.mark.webtest
|
||||
|
||||
or if you need to use multiple markers you can use a list::
|
||||
or if you need to use multiple markers you can use a list:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
class TestClass(object):
|
||||
pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
|
||||
|
||||
@@ -301,18 +328,19 @@ Marking individual tests when using parametrize
|
||||
|
||||
When using parametrize, applying a mark will make it apply
|
||||
to each individual test. However it is also possible to
|
||||
apply a marker to an individual test instance::
|
||||
apply a marker to an individual test instance:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.foo
|
||||
@pytest.mark.parametrize(("n", "expected"), [
|
||||
(1, 2),
|
||||
pytest.param((1, 3), marks=pytest.mark.bar),
|
||||
(2, 3),
|
||||
])
|
||||
@pytest.mark.parametrize(
|
||||
("n", "expected"), [(1, 2), pytest.param((1, 3), marks=pytest.mark.bar), (2, 3)]
|
||||
)
|
||||
def test_increment(n, expected):
|
||||
assert n + 1 == expected
|
||||
assert n + 1 == expected
|
||||
|
||||
In this example the mark "foo" will apply to each of the three
|
||||
tests, whereas the "bar" mark is only applied to the second test.
|
||||
@@ -328,31 +356,46 @@ Custom marker and command line option to control test runs
|
||||
Plugins can provide custom markers and implement specific behaviour
|
||||
based on it. This is a self-contained example which adds a command
|
||||
line option and a parametrized test function marker to run tests
|
||||
specifies via named environments::
|
||||
specifies via named environments:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("-E", action="store", metavar="NAME",
|
||||
help="only run tests matching the environment NAME.")
|
||||
parser.addoption(
|
||||
"-E",
|
||||
action="store",
|
||||
metavar="NAME",
|
||||
help="only run tests matching the environment NAME.",
|
||||
)
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
# register an additional marker
|
||||
config.addinivalue_line("markers",
|
||||
"env(name): mark test to run only on named environment")
|
||||
config.addinivalue_line(
|
||||
"markers", "env(name): mark test to run only on named environment"
|
||||
)
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
envnames = [mark.args[0] for mark in item.iter_markers(name='env')]
|
||||
envnames = [mark.args[0] for mark in item.iter_markers(name="env")]
|
||||
if envnames:
|
||||
if item.config.getoption("-E") not in envnames:
|
||||
pytest.skip("test requires env in %r" % envnames)
|
||||
|
||||
A test file using this local plugin::
|
||||
A test file using this local plugin:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_someenv.py
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.env("stage1")
|
||||
def test_basic_db_operation():
|
||||
pass
|
||||
@@ -366,7 +409,7 @@ the test needs:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_someenv.py s [100%]
|
||||
@@ -381,14 +424,16 @@ and here is one that specifies exactly the environment needed:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_someenv.py . [100%]
|
||||
|
||||
========================= 1 passed in 0.12 seconds =========================
|
||||
|
||||
The ``--markers`` option always gives you a list of available markers::
|
||||
The ``--markers`` option always gives you a list of available markers:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest --markers
|
||||
@pytest.mark.env(name): mark test to run only on named environment
|
||||
@@ -417,25 +462,32 @@ Passing a callable to custom markers
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
Below is the config file that will be used in the next examples::
|
||||
Below is the config file that will be used in the next examples:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
import sys
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
for marker in item.iter_markers(name='my_marker'):
|
||||
for marker in item.iter_markers(name="my_marker"):
|
||||
print(marker)
|
||||
sys.stdout.flush()
|
||||
|
||||
A custom marker can have its argument set, i.e. ``args`` and ``kwargs`` properties, defined by either invoking it as a callable or using ``pytest.mark.MARKER_NAME.with_args``. These two methods achieve the same effect most of the time.
|
||||
|
||||
However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator <mark>`). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue::
|
||||
However, if there is a callable as the single positional argument with no keyword arguments, using the ``pytest.mark.MARKER_NAME(c)`` will not pass ``c`` as a positional argument but decorate ``c`` with the custom marker (see :ref:`MarkDecorator <mark>`). Fortunately, ``pytest.mark.MARKER_NAME.with_args`` comes to the rescue:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_custom_marker.py
|
||||
import pytest
|
||||
|
||||
|
||||
def hello_world(*args, **kwargs):
|
||||
return 'Hello World'
|
||||
return "Hello World"
|
||||
|
||||
|
||||
@pytest.mark.my_marker.with_args(hello_world)
|
||||
def test_with_args():
|
||||
@@ -461,12 +513,16 @@ Reading markers which were set from multiple places
|
||||
.. regendoc:wipe
|
||||
|
||||
If you are heavily using markers in your test suite you may encounter the case where a marker is applied several times to a test function. From plugin
|
||||
code you can read over all such settings. Example::
|
||||
code you can read over all such settings. Example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_mark_three_times.py
|
||||
import pytest
|
||||
|
||||
pytestmark = pytest.mark.glob("module", x=1)
|
||||
|
||||
|
||||
@pytest.mark.glob("class", x=2)
|
||||
class TestClass(object):
|
||||
@pytest.mark.glob("function", x=3)
|
||||
@@ -474,13 +530,16 @@ code you can read over all such settings. Example::
|
||||
pass
|
||||
|
||||
Here we have the marker "glob" applied three times to the same
|
||||
test function. From a conftest file we can read it like this::
|
||||
test function. From a conftest file we can read it like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
import sys
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
for mark in item.iter_markers(name='glob'):
|
||||
for mark in item.iter_markers(name="glob"):
|
||||
print("glob args=%s kwargs=%s" % (mark.args, mark.kwargs))
|
||||
sys.stdout.flush()
|
||||
|
||||
@@ -504,7 +563,9 @@ Consider you have a test suite which marks tests for particular platforms,
|
||||
namely ``pytest.mark.darwin``, ``pytest.mark.win32`` etc. and you
|
||||
also have tests that run on all platforms and have no specific
|
||||
marker. If you now want to have a way to only run the tests
|
||||
for your particular platform, you could use the following plugin::
|
||||
for your particular platform, you could use the following plugin:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
#
|
||||
@@ -513,6 +574,7 @@ for your particular platform, you could use the following plugin::
|
||||
|
||||
ALL = set("darwin linux win32".split())
|
||||
|
||||
|
||||
def pytest_runtest_setup(item):
|
||||
supported_platforms = ALL.intersection(mark.name for mark in item.iter_markers())
|
||||
plat = sys.platform
|
||||
@@ -520,24 +582,30 @@ for your particular platform, you could use the following plugin::
|
||||
pytest.skip("cannot run on platform %s" % (plat))
|
||||
|
||||
then tests will be skipped if they were specified for a different platform.
|
||||
Let's do a little test file to show how this looks like::
|
||||
Let's do a little test file to show how this looks like:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_plat.py
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.darwin
|
||||
def test_if_apple_is_evil():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.linux
|
||||
def test_if_linux_works():
|
||||
pass
|
||||
|
||||
|
||||
@pytest.mark.win32
|
||||
def test_if_win32_crashes():
|
||||
pass
|
||||
|
||||
|
||||
def test_runs_everywhere():
|
||||
pass
|
||||
|
||||
@@ -549,13 +617,13 @@ then you will see two tests skipped and two executed tests as expected:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items
|
||||
|
||||
test_plat.py s.s. [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [2] $REGENDOC_TMPDIR/conftest.py:12: cannot run on platform linux
|
||||
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [2] $REGENDOC_TMPDIR/conftest.py:13: cannot run on platform linux
|
||||
=================== 2 passed, 2 skipped in 0.12 seconds ====================
|
||||
|
||||
Note that if you specify a platform via the marker-command line option like this:
|
||||
@@ -566,7 +634,7 @@ Note that if you specify a platform via the marker-command line option like this
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items / 3 deselected / 1 selected
|
||||
|
||||
test_plat.py . [100%]
|
||||
@@ -583,28 +651,38 @@ Automatically adding markers based on test names
|
||||
If you a test suite where test function names indicate a certain
|
||||
type of test, you can implement a hook that automatically defines
|
||||
markers so that you can use the ``-m`` option with it. Let's look
|
||||
at this test module::
|
||||
at this test module:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_module.py
|
||||
|
||||
|
||||
def test_interface_simple():
|
||||
assert 0
|
||||
|
||||
|
||||
def test_interface_complex():
|
||||
assert 0
|
||||
|
||||
|
||||
def test_event_simple():
|
||||
assert 0
|
||||
|
||||
|
||||
def test_something_else():
|
||||
assert 0
|
||||
|
||||
We want to dynamically define two markers and can do it in a
|
||||
``conftest.py`` plugin::
|
||||
``conftest.py`` plugin:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def pytest_collection_modifyitems(items):
|
||||
for item in items:
|
||||
if "interface" in item.nodeid:
|
||||
@@ -620,18 +698,18 @@ We can now use the ``-m option`` to select one set:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items / 2 deselected / 2 selected
|
||||
|
||||
test_module.py FF [100%]
|
||||
|
||||
================================= FAILURES =================================
|
||||
__________________________ test_interface_simple ___________________________
|
||||
test_module.py:3: in test_interface_simple
|
||||
test_module.py:4: in test_interface_simple
|
||||
assert 0
|
||||
E assert 0
|
||||
__________________________ test_interface_complex __________________________
|
||||
test_module.py:6: in test_interface_complex
|
||||
test_module.py:8: in test_interface_complex
|
||||
assert 0
|
||||
E assert 0
|
||||
================== 2 failed, 2 deselected in 0.12 seconds ==================
|
||||
@@ -644,22 +722,22 @@ or to select both "event" and "interface" tests:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items / 1 deselected / 3 selected
|
||||
|
||||
test_module.py FFF [100%]
|
||||
|
||||
================================= FAILURES =================================
|
||||
__________________________ test_interface_simple ___________________________
|
||||
test_module.py:3: in test_interface_simple
|
||||
test_module.py:4: in test_interface_simple
|
||||
assert 0
|
||||
E assert 0
|
||||
__________________________ test_interface_complex __________________________
|
||||
test_module.py:6: in test_interface_complex
|
||||
test_module.py:8: in test_interface_complex
|
||||
assert 0
|
||||
E assert 0
|
||||
____________________________ test_event_simple _____________________________
|
||||
test_module.py:9: in test_event_simple
|
||||
test_module.py:12: in test_event_simple
|
||||
assert 0
|
||||
E assert 0
|
||||
================== 3 failed, 1 deselected in 0.12 seconds ==================
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
module containing a parametrized tests testing cross-python
|
||||
serialization via the pickle module.
|
||||
|
||||
@@ -31,7 +31,7 @@ now execute the test specification:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython
|
||||
collected 2 items
|
||||
|
||||
test_simple.yml F. [100%]
|
||||
@@ -66,7 +66,7 @@ consulted when reporting in ``verbose`` mode:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_simple.yml::hello FAILED [ 50%]
|
||||
@@ -90,7 +90,7 @@ interesting to just look at the collection tree:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR/nonpython
|
||||
collected 2 items
|
||||
<Package $REGENDOC_TMPDIR/nonpython>
|
||||
<YamlFile test_simple.yml>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# content of conftest.py
|
||||
import pytest
|
||||
|
||||
|
||||
@@ -146,7 +146,7 @@ objects, they are still using the default pytest representation:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 8 items
|
||||
<Module test_time.py>
|
||||
<Function test_timedistance_v0[a0-b0-expected0]>
|
||||
@@ -205,7 +205,7 @@ this is a fully self-contained example which you can run with:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items
|
||||
|
||||
test_scenarios.py .... [100%]
|
||||
@@ -220,7 +220,7 @@ If you just collect tests you'll also nicely see 'advanced' and 'basic' as varia
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items
|
||||
<Module test_scenarios.py>
|
||||
<Class TestSampleWithScenarios>
|
||||
@@ -287,7 +287,7 @@ Let's first see how it looks like at collection time:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
<Module test_backends.py>
|
||||
<Function test_db_initialized[d1]>
|
||||
@@ -353,7 +353,7 @@ The result of this test will be successful:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
<Module test_indirect_list.py>
|
||||
<Function test_indirect[a-b]>
|
||||
@@ -411,8 +411,6 @@ argument sets to use for each test function. Let's run it:
|
||||
def test_equals(self, a, b):
|
||||
> assert a == b
|
||||
E assert 1 == 2
|
||||
E -1
|
||||
E +2
|
||||
|
||||
test_parametrize.py:18: AssertionError
|
||||
1 failed, 2 passed in 0.12 seconds
|
||||
@@ -436,8 +434,10 @@ Running it results in some skips if we don't have all the python interpreters in
|
||||
.. code-block:: pytest
|
||||
|
||||
. $ pytest -rs -q multipython.py
|
||||
........................... [100%]
|
||||
27 passed in 0.12 seconds
|
||||
...sss...sssssssss...sss... [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [15] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.4' not found
|
||||
12 passed, 15 skipped in 0.12 seconds
|
||||
|
||||
Indirect parametrization of optional implementations/imports
|
||||
--------------------------------------------------------------------
|
||||
@@ -488,13 +488,13 @@ If you run this with reporting for skips enabled:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [1] $REGENDOC_TMPDIR/conftest.py:11: could not import 'opt2'
|
||||
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [1] $REGENDOC_TMPDIR/conftest.py:11: could not import 'opt2': No module named 'opt2'
|
||||
=================== 1 passed, 1 skipped in 0.12 seconds ====================
|
||||
|
||||
You'll see that we don't have an ``opt2`` module and thus the second test run
|
||||
@@ -515,21 +515,25 @@ Set marks or test ID for individual parametrized test
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Use ``pytest.param`` to apply marks or set test ID to individual parametrized test.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_pytest_param_example.py
|
||||
import pytest
|
||||
@pytest.mark.parametrize('test_input,expected', [
|
||||
('3+5', 8),
|
||||
pytest.param('1+7', 8,
|
||||
marks=pytest.mark.basic),
|
||||
pytest.param('2+4', 6,
|
||||
marks=pytest.mark.basic,
|
||||
id='basic_2+4'),
|
||||
pytest.param('6*9', 42,
|
||||
marks=[pytest.mark.basic, pytest.mark.xfail],
|
||||
id='basic_6*9'),
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_input,expected",
|
||||
[
|
||||
("3+5", 8),
|
||||
pytest.param("1+7", 8, marks=pytest.mark.basic),
|
||||
pytest.param("2+4", 6, marks=pytest.mark.basic, id="basic_2+4"),
|
||||
pytest.param(
|
||||
"6*9", 42, marks=[pytest.mark.basic, pytest.mark.xfail], id="basic_6*9"
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_eval(test_input, expected):
|
||||
assert eval(test_input) == expected
|
||||
|
||||
@@ -546,7 +550,7 @@ Then run ``pytest`` with verbose mode and with only the ``basic`` marker:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 17 items / 14 deselected / 3 selected
|
||||
|
||||
test_pytest_param_example.py::test_eval[1+7-8] PASSED [ 33%]
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
def test_exception_syntax():
|
||||
try:
|
||||
0 / 0
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# run this with $ pytest --collect-only test_collectonly.py
|
||||
#
|
||||
|
||||
|
||||
@@ -6,7 +6,9 @@ Ignore paths during test collection
|
||||
|
||||
You can easily ignore certain test directories and modules during collection
|
||||
by passing the ``--ignore=path`` option on the cli. ``pytest`` allows multiple
|
||||
``--ignore`` options. Example::
|
||||
``--ignore`` options. Example:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
tests/
|
||||
|-- example
|
||||
@@ -57,7 +59,9 @@ Keeping duplicate paths specified from command line
|
||||
----------------------------------------------------
|
||||
|
||||
Default behavior of ``pytest`` is to ignore duplicate paths specified from the command line.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
pytest path_a path_a
|
||||
|
||||
@@ -68,7 +72,9 @@ Example::
|
||||
Just collect tests once.
|
||||
|
||||
To collect duplicate tests, use the ``--keep-duplicates`` option on the cli.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
pytest --keep-duplicates path_a path_a
|
||||
|
||||
@@ -78,7 +84,9 @@ Example::
|
||||
|
||||
As the collector just works on directories, if you specify twice a single test file, ``pytest`` will
|
||||
still collect it twice, no matter if the ``--keep-duplicates`` is not specified.
|
||||
Example::
|
||||
Example:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
pytest test_a.py test_a.py
|
||||
|
||||
@@ -90,7 +98,9 @@ Example::
|
||||
Changing directory recursion
|
||||
-----------------------------------------------------
|
||||
|
||||
You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory::
|
||||
You can set the :confval:`norecursedirs` option in an ini-file, for example your ``pytest.ini`` in the project root directory:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
@@ -106,7 +116,9 @@ Changing naming conventions
|
||||
You can configure different naming conventions by setting
|
||||
the :confval:`python_files`, :confval:`python_classes` and
|
||||
:confval:`python_functions` configuration options.
|
||||
Here is an example::
|
||||
Here is an example:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
# Example 1: have pytest look for "check" instead of "test"
|
||||
@@ -145,7 +157,9 @@ The test collection would look like this:
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
|
||||
You can check for multiple glob patterns by adding a space between the patterns::
|
||||
You can check for multiple glob patterns by adding a space between the patterns:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# Example 2: have pytest look for files with "test" and "example"
|
||||
# content of pytest.ini, tox.ini, or setup.cfg file (replace "pytest"
|
||||
@@ -165,13 +179,17 @@ Interpreting cmdline arguments as Python packages
|
||||
You can use the ``--pyargs`` option to make ``pytest`` try
|
||||
interpreting arguments as python package names, deriving
|
||||
their file system path and then running the test. For
|
||||
example if you have unittest2 installed you can type::
|
||||
example if you have unittest2 installed you can type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pyargs unittest2.test.test_skipping -q
|
||||
|
||||
which would run the respective test module. Like with
|
||||
other options, through an ini-file and the :confval:`addopts` option you
|
||||
can make this change more permanently::
|
||||
can make this change more permanently:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
@@ -209,7 +227,9 @@ Customizing test collection
|
||||
|
||||
.. regendoc:wipe
|
||||
|
||||
You can easily instruct ``pytest`` to discover tests from every Python file::
|
||||
You can easily instruct ``pytest`` to discover tests from every Python file:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
# content of pytest.ini
|
||||
[pytest]
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
|
||||
.. _`tbreportdemo`:
|
||||
|
||||
Demo of Python failure reports with pytest
|
||||
==================================================
|
||||
==========================================
|
||||
|
||||
Here is a nice run of several tens of failures
|
||||
and how ``pytest`` presents things (unfortunately
|
||||
not showing the nice colors here in the HTML that you
|
||||
get on the terminal - we are working on that):
|
||||
Here is a nice run of several failures and how ``pytest`` presents things:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
@@ -15,7 +11,7 @@ get on the terminal - we are working on that):
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR/assertion, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR/assertion
|
||||
collected 44 items
|
||||
|
||||
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF [100%]
|
||||
@@ -30,7 +26,7 @@ get on the terminal - we are working on that):
|
||||
> assert param1 * 2 < param2
|
||||
E assert (3 * 2) < 6
|
||||
|
||||
failure_demo.py:22: AssertionError
|
||||
failure_demo.py:21: AssertionError
|
||||
_________________________ TestFailing.test_simple __________________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0xdeadbeef>
|
||||
@@ -47,7 +43,7 @@ get on the terminal - we are working on that):
|
||||
E + where 42 = <function TestFailing.test_simple.<locals>.f at 0xdeadbeef>()
|
||||
E + and 43 = <function TestFailing.test_simple.<locals>.g at 0xdeadbeef>()
|
||||
|
||||
failure_demo.py:33: AssertionError
|
||||
failure_demo.py:32: AssertionError
|
||||
____________________ TestFailing.test_simple_multiline _____________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0xdeadbeef>
|
||||
@@ -55,7 +51,7 @@ get on the terminal - we are working on that):
|
||||
def test_simple_multiline(self):
|
||||
> otherfunc_multi(42, 6 * 9)
|
||||
|
||||
failure_demo.py:36:
|
||||
failure_demo.py:35:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
a = 42, b = 54
|
||||
@@ -64,7 +60,7 @@ get on the terminal - we are working on that):
|
||||
> assert a == b
|
||||
E assert 42 == 54
|
||||
|
||||
failure_demo.py:17: AssertionError
|
||||
failure_demo.py:16: AssertionError
|
||||
___________________________ TestFailing.test_not ___________________________
|
||||
|
||||
self = <failure_demo.TestFailing object at 0xdeadbeef>
|
||||
@@ -77,7 +73,7 @@ get on the terminal - we are working on that):
|
||||
E assert not 42
|
||||
E + where 42 = <function TestFailing.test_not.<locals>.f at 0xdeadbeef>()
|
||||
|
||||
failure_demo.py:42: AssertionError
|
||||
failure_demo.py:41: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_text _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -88,7 +84,7 @@ get on the terminal - we are working on that):
|
||||
E - spam
|
||||
E + eggs
|
||||
|
||||
failure_demo.py:47: AssertionError
|
||||
failure_demo.py:46: AssertionError
|
||||
_____________ TestSpecialisedExplanations.test_eq_similar_text _____________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -101,7 +97,7 @@ get on the terminal - we are working on that):
|
||||
E + foo 2 bar
|
||||
E ? ^
|
||||
|
||||
failure_demo.py:50: AssertionError
|
||||
failure_demo.py:49: AssertionError
|
||||
____________ TestSpecialisedExplanations.test_eq_multiline_text ____________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -114,7 +110,7 @@ get on the terminal - we are working on that):
|
||||
E + eggs
|
||||
E bar
|
||||
|
||||
failure_demo.py:53: AssertionError
|
||||
failure_demo.py:52: AssertionError
|
||||
______________ TestSpecialisedExplanations.test_eq_long_text _______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -131,7 +127,7 @@ get on the terminal - we are working on that):
|
||||
E + 1111111111b222222222
|
||||
E ? ^
|
||||
|
||||
failure_demo.py:58: AssertionError
|
||||
failure_demo.py:57: AssertionError
|
||||
_________ TestSpecialisedExplanations.test_eq_long_text_multiline __________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -151,7 +147,7 @@ get on the terminal - we are working on that):
|
||||
E
|
||||
E ...Full output truncated (7 lines hidden), use '-vv' to show
|
||||
|
||||
failure_demo.py:63: AssertionError
|
||||
failure_demo.py:62: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_list _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -162,7 +158,7 @@ get on the terminal - we are working on that):
|
||||
E At index 2 diff: 2 != 3
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:66: AssertionError
|
||||
failure_demo.py:65: AssertionError
|
||||
______________ TestSpecialisedExplanations.test_eq_list_long _______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -175,7 +171,7 @@ get on the terminal - we are working on that):
|
||||
E At index 100 diff: 1 != 2
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:71: AssertionError
|
||||
failure_demo.py:70: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_dict _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -186,14 +182,14 @@ get on the terminal - we are working on that):
|
||||
E Omitting 1 identical items, use -vv to show
|
||||
E Differing items:
|
||||
E {'b': 1} != {'b': 2}
|
||||
E Left contains more items:
|
||||
E Left contains 1 more item:
|
||||
E {'c': 0}
|
||||
E Right contains more items:
|
||||
E Right contains 1 more item:
|
||||
E {'d': 0}...
|
||||
E
|
||||
E ...Full output truncated (2 lines hidden), use '-vv' to show
|
||||
|
||||
failure_demo.py:74: AssertionError
|
||||
failure_demo.py:73: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_eq_set __________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -211,7 +207,7 @@ get on the terminal - we are working on that):
|
||||
E
|
||||
E ...Full output truncated (2 lines hidden), use '-vv' to show
|
||||
|
||||
failure_demo.py:77: AssertionError
|
||||
failure_demo.py:76: AssertionError
|
||||
_____________ TestSpecialisedExplanations.test_eq_longer_list ______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -219,10 +215,10 @@ get on the terminal - we are working on that):
|
||||
def test_eq_longer_list(self):
|
||||
> assert [1, 2] == [1, 2, 3]
|
||||
E assert [1, 2] == [1, 2, 3]
|
||||
E Right contains more items, first extra item: 3
|
||||
E Right contains one more item: 3
|
||||
E Use -v to get the full diff
|
||||
|
||||
failure_demo.py:80: AssertionError
|
||||
failure_demo.py:79: AssertionError
|
||||
_________________ TestSpecialisedExplanations.test_in_list _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -231,7 +227,7 @@ get on the terminal - we are working on that):
|
||||
> assert 1 in [0, 2, 3, 4, 5]
|
||||
E assert 1 in [0, 2, 3, 4, 5]
|
||||
|
||||
failure_demo.py:83: AssertionError
|
||||
failure_demo.py:82: AssertionError
|
||||
__________ TestSpecialisedExplanations.test_not_in_text_multiline __________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -250,7 +246,7 @@ get on the terminal - we are working on that):
|
||||
E
|
||||
E ...Full output truncated (2 lines hidden), use '-vv' to show
|
||||
|
||||
failure_demo.py:87: AssertionError
|
||||
failure_demo.py:86: AssertionError
|
||||
___________ TestSpecialisedExplanations.test_not_in_text_single ____________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -263,7 +259,7 @@ get on the terminal - we are working on that):
|
||||
E single foo line
|
||||
E ? +++
|
||||
|
||||
failure_demo.py:91: AssertionError
|
||||
failure_demo.py:90: AssertionError
|
||||
_________ TestSpecialisedExplanations.test_not_in_text_single_long _________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -276,7 +272,7 @@ get on the terminal - we are working on that):
|
||||
E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||
E ? +++
|
||||
|
||||
failure_demo.py:95: AssertionError
|
||||
failure_demo.py:94: AssertionError
|
||||
______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -289,7 +285,7 @@ get on the terminal - we are working on that):
|
||||
E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||
E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
failure_demo.py:99: AssertionError
|
||||
failure_demo.py:98: AssertionError
|
||||
______________ TestSpecialisedExplanations.test_eq_dataclass _______________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -310,7 +306,7 @@ get on the terminal - we are working on that):
|
||||
E Differing attributes:
|
||||
E b: 'b' != 'c'
|
||||
|
||||
failure_demo.py:111: AssertionError
|
||||
failure_demo.py:110: AssertionError
|
||||
________________ TestSpecialisedExplanations.test_eq_attrs _________________
|
||||
|
||||
self = <failure_demo.TestSpecialisedExplanations object at 0xdeadbeef>
|
||||
@@ -331,7 +327,7 @@ get on the terminal - we are working on that):
|
||||
E Differing attributes:
|
||||
E b: 'b' != 'c'
|
||||
|
||||
failure_demo.py:123: AssertionError
|
||||
failure_demo.py:122: AssertionError
|
||||
______________________________ test_attribute ______________________________
|
||||
|
||||
def test_attribute():
|
||||
@@ -343,7 +339,7 @@ get on the terminal - we are working on that):
|
||||
E assert 1 == 2
|
||||
E + where 1 = <failure_demo.test_attribute.<locals>.Foo object at 0xdeadbeef>.b
|
||||
|
||||
failure_demo.py:131: AssertionError
|
||||
failure_demo.py:130: AssertionError
|
||||
_________________________ test_attribute_instance __________________________
|
||||
|
||||
def test_attribute_instance():
|
||||
@@ -355,7 +351,7 @@ get on the terminal - we are working on that):
|
||||
E + where 1 = <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef>.b
|
||||
E + where <failure_demo.test_attribute_instance.<locals>.Foo object at 0xdeadbeef> = <class 'failure_demo.test_attribute_instance.<locals>.Foo'>()
|
||||
|
||||
failure_demo.py:138: AssertionError
|
||||
failure_demo.py:137: AssertionError
|
||||
__________________________ test_attribute_failure __________________________
|
||||
|
||||
def test_attribute_failure():
|
||||
@@ -368,7 +364,7 @@ get on the terminal - we are working on that):
|
||||
i = Foo()
|
||||
> assert i.b == 2
|
||||
|
||||
failure_demo.py:149:
|
||||
failure_demo.py:148:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
self = <failure_demo.test_attribute_failure.<locals>.Foo object at 0xdeadbeef>
|
||||
@@ -377,7 +373,7 @@ get on the terminal - we are working on that):
|
||||
> raise Exception("Failed to get attrib")
|
||||
E Exception: Failed to get attrib
|
||||
|
||||
failure_demo.py:144: Exception
|
||||
failure_demo.py:143: Exception
|
||||
_________________________ test_attribute_multiple __________________________
|
||||
|
||||
def test_attribute_multiple():
|
||||
@@ -394,7 +390,7 @@ get on the terminal - we are working on that):
|
||||
E + and 2 = <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef>.b
|
||||
E + where <failure_demo.test_attribute_multiple.<locals>.Bar object at 0xdeadbeef> = <class 'failure_demo.test_attribute_multiple.<locals>.Bar'>()
|
||||
|
||||
failure_demo.py:159: AssertionError
|
||||
failure_demo.py:158: AssertionError
|
||||
__________________________ TestRaises.test_raises __________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
@@ -404,7 +400,7 @@ get on the terminal - we are working on that):
|
||||
> raises(TypeError, int, s)
|
||||
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||
|
||||
failure_demo.py:169: ValueError
|
||||
failure_demo.py:168: ValueError
|
||||
______________________ TestRaises.test_raises_doesnt _______________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
@@ -413,7 +409,7 @@ get on the terminal - we are working on that):
|
||||
> raises(IOError, int, "3")
|
||||
E Failed: DID NOT RAISE <class 'OSError'>
|
||||
|
||||
failure_demo.py:172: Failed
|
||||
failure_demo.py:171: Failed
|
||||
__________________________ TestRaises.test_raise ___________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
@@ -422,7 +418,7 @@ get on the terminal - we are working on that):
|
||||
> raise ValueError("demo error")
|
||||
E ValueError: demo error
|
||||
|
||||
failure_demo.py:175: ValueError
|
||||
failure_demo.py:174: ValueError
|
||||
________________________ TestRaises.test_tupleerror ________________________
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
@@ -431,7 +427,7 @@ get on the terminal - we are working on that):
|
||||
> a, b = [1] # NOQA
|
||||
E ValueError: not enough values to unpack (expected 2, got 1)
|
||||
|
||||
failure_demo.py:178: ValueError
|
||||
failure_demo.py:177: ValueError
|
||||
______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
|
||||
|
||||
self = <failure_demo.TestRaises object at 0xdeadbeef>
|
||||
@@ -442,7 +438,7 @@ get on the terminal - we are working on that):
|
||||
> a, b = items.pop()
|
||||
E TypeError: 'int' object is not iterable
|
||||
|
||||
failure_demo.py:183: TypeError
|
||||
failure_demo.py:182: TypeError
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
items is [1, 2, 3]
|
||||
________________________ TestRaises.test_some_error ________________________
|
||||
@@ -453,7 +449,7 @@ get on the terminal - we are working on that):
|
||||
> if namenotexi: # NOQA
|
||||
E NameError: name 'namenotexi' is not defined
|
||||
|
||||
failure_demo.py:186: NameError
|
||||
failure_demo.py:185: NameError
|
||||
____________________ test_dynamic_compile_shows_nicely _____________________
|
||||
|
||||
def test_dynamic_compile_shows_nicely():
|
||||
@@ -464,18 +460,18 @@ get on the terminal - we are working on that):
|
||||
name = "abc-123"
|
||||
module = imp.new_module(name)
|
||||
code = _pytest._code.compile(src, name, "exec")
|
||||
six.exec_(code, module.__dict__)
|
||||
exec(code, module.__dict__)
|
||||
sys.modules[name] = module
|
||||
> module.foo()
|
||||
|
||||
failure_demo.py:204:
|
||||
failure_demo.py:203:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
def foo():
|
||||
> assert 1 == 0
|
||||
E AssertionError
|
||||
|
||||
<0-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:201>:2: AssertionError
|
||||
<0-codegen 'abc-123' $REGENDOC_TMPDIR/assertion/failure_demo.py:200>:2: AssertionError
|
||||
____________________ TestMoreErrors.test_complex_error _____________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -489,9 +485,9 @@ get on the terminal - we are working on that):
|
||||
|
||||
> somefunc(f(), g())
|
||||
|
||||
failure_demo.py:215:
|
||||
failure_demo.py:214:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
failure_demo.py:13: in somefunc
|
||||
failure_demo.py:12: in somefunc
|
||||
otherfunc(x, y)
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
@@ -501,7 +497,7 @@ get on the terminal - we are working on that):
|
||||
> assert a == b
|
||||
E assert 44 == 43
|
||||
|
||||
failure_demo.py:9: AssertionError
|
||||
failure_demo.py:8: AssertionError
|
||||
___________________ TestMoreErrors.test_z1_unpack_error ____________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -511,7 +507,7 @@ get on the terminal - we are working on that):
|
||||
> a, b = items
|
||||
E ValueError: not enough values to unpack (expected 2, got 0)
|
||||
|
||||
failure_demo.py:219: ValueError
|
||||
failure_demo.py:218: ValueError
|
||||
____________________ TestMoreErrors.test_z2_type_error _____________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -521,7 +517,7 @@ get on the terminal - we are working on that):
|
||||
> a, b = items
|
||||
E TypeError: 'int' object is not iterable
|
||||
|
||||
failure_demo.py:223: TypeError
|
||||
failure_demo.py:222: TypeError
|
||||
______________________ TestMoreErrors.test_startswith ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -534,7 +530,7 @@ get on the terminal - we are working on that):
|
||||
E + where False = <built-in method startswith of str object at 0xdeadbeef>('456')
|
||||
E + where <built-in method startswith of str object at 0xdeadbeef> = '123'.startswith
|
||||
|
||||
failure_demo.py:228: AssertionError
|
||||
failure_demo.py:227: AssertionError
|
||||
__________________ TestMoreErrors.test_startswith_nested ___________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -553,7 +549,7 @@ get on the terminal - we are working on that):
|
||||
E + where '123' = <function TestMoreErrors.test_startswith_nested.<locals>.f at 0xdeadbeef>()
|
||||
E + and '456' = <function TestMoreErrors.test_startswith_nested.<locals>.g at 0xdeadbeef>()
|
||||
|
||||
failure_demo.py:237: AssertionError
|
||||
failure_demo.py:236: AssertionError
|
||||
_____________________ TestMoreErrors.test_global_func ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -564,7 +560,7 @@ get on the terminal - we are working on that):
|
||||
E + where False = isinstance(43, float)
|
||||
E + where 43 = globf(42)
|
||||
|
||||
failure_demo.py:240: AssertionError
|
||||
failure_demo.py:239: AssertionError
|
||||
_______________________ TestMoreErrors.test_instance _______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -575,7 +571,7 @@ get on the terminal - we are working on that):
|
||||
E assert 42 != 42
|
||||
E + where 42 = <failure_demo.TestMoreErrors object at 0xdeadbeef>.x
|
||||
|
||||
failure_demo.py:244: AssertionError
|
||||
failure_demo.py:243: AssertionError
|
||||
_______________________ TestMoreErrors.test_compare ________________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -585,7 +581,7 @@ get on the terminal - we are working on that):
|
||||
E assert 11 < 5
|
||||
E + where 11 = globf(10)
|
||||
|
||||
failure_demo.py:247: AssertionError
|
||||
failure_demo.py:246: AssertionError
|
||||
_____________________ TestMoreErrors.test_try_finally ______________________
|
||||
|
||||
self = <failure_demo.TestMoreErrors object at 0xdeadbeef>
|
||||
@@ -596,7 +592,7 @@ get on the terminal - we are working on that):
|
||||
> assert x == 0
|
||||
E assert 1 == 0
|
||||
|
||||
failure_demo.py:252: AssertionError
|
||||
failure_demo.py:251: AssertionError
|
||||
___________________ TestCustomAssertMsg.test_single_line ___________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
|
||||
@@ -611,7 +607,7 @@ get on the terminal - we are working on that):
|
||||
E assert 1 == 2
|
||||
E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_single_line.<locals>.A'>.a
|
||||
|
||||
failure_demo.py:263: AssertionError
|
||||
failure_demo.py:262: AssertionError
|
||||
____________________ TestCustomAssertMsg.test_multiline ____________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
|
||||
@@ -630,7 +626,7 @@ get on the terminal - we are working on that):
|
||||
E assert 1 == 2
|
||||
E + where 1 = <class 'failure_demo.TestCustomAssertMsg.test_multiline.<locals>.A'>.a
|
||||
|
||||
failure_demo.py:270: AssertionError
|
||||
failure_demo.py:269: AssertionError
|
||||
___________________ TestCustomAssertMsg.test_custom_repr ___________________
|
||||
|
||||
self = <failure_demo.TestCustomAssertMsg object at 0xdeadbeef>
|
||||
@@ -652,5 +648,5 @@ get on the terminal - we are working on that):
|
||||
E assert 1 == 2
|
||||
E + where 1 = This is JSON\n{\n 'foo': 'bar'\n}.a
|
||||
|
||||
failure_demo.py:283: AssertionError
|
||||
failure_demo.py:282: AssertionError
|
||||
======================== 44 failed in 0.12 seconds =========================
|
||||
|
||||
@@ -107,7 +107,7 @@ the command line arguments before they get processed:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
# setuptools plugin
|
||||
import sys
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ directory with the above conftest.py:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 0 items
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
@@ -190,13 +190,13 @@ and when running it will see a skipped "slow" test:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py .s [100%]
|
||||
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [1] test_module.py:8: need --runslow option to run
|
||||
|
||||
=================== 1 passed, 1 skipped in 0.12 seconds ====================
|
||||
|
||||
Or run it including the ``slow`` marked test:
|
||||
@@ -207,7 +207,7 @@ Or run it including the ``slow`` marked test:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py .. [100%]
|
||||
@@ -351,7 +351,7 @@ which will add the string to the test header accordingly:
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
project deps: mylib-1.1
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 0 items
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
@@ -381,7 +381,7 @@ which will add info only when run with "--v":
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
info1: did you know that ...
|
||||
did you?
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 0 items
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
@@ -394,7 +394,7 @@ and nothing when run plainly:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 0 items
|
||||
|
||||
======================= no tests ran in 0.12 seconds =======================
|
||||
@@ -434,7 +434,7 @@ Now we can profile which test functions execute the slowest:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 3 items
|
||||
|
||||
test_some_are_slow.py ... [100%]
|
||||
@@ -509,7 +509,7 @@ If we run this:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 4 items
|
||||
|
||||
test_step.py .Fx. [100%]
|
||||
@@ -593,7 +593,7 @@ We can run this:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 7 items
|
||||
|
||||
test_step.py .Fx. [ 57%]
|
||||
@@ -606,7 +606,7 @@ We can run this:
|
||||
file $REGENDOC_TMPDIR/b/test_error.py, line 1
|
||||
def test_root(db): # no db here, will error out
|
||||
E fixture 'db' not found
|
||||
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
|
||||
> available fixtures: cache, capfd, capfdbinary, caplog, capsys, capsysbinary, doctest_namespace, monkeypatch, pytestconfig, record_property, record_testsuite_property, record_xml_attribute, recwarn, tmp_path, tmp_path_factory, tmpdir, tmpdir_factory
|
||||
> use 'pytest --fixtures [testpath]' for help on them.
|
||||
|
||||
$REGENDOC_TMPDIR/b/test_error.py:1
|
||||
@@ -707,7 +707,7 @@ and run them:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF [100%]
|
||||
@@ -731,7 +731,9 @@ and run them:
|
||||
test_module.py:6: AssertionError
|
||||
========================= 2 failed in 0.12 seconds =========================
|
||||
|
||||
you will have a "failures" file which contains the failing test ids::
|
||||
you will have a "failures" file which contains the failing test ids:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ cat failures
|
||||
test_module.py::test_fail1 (PYTEST_TMPDIR/test_fail10)
|
||||
@@ -809,7 +811,7 @@ and run it:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 3 items
|
||||
|
||||
test_module.py Esetting up a test failed! test_module.py::test_setup_fails
|
||||
@@ -852,7 +854,7 @@ information.
|
||||
``PYTEST_CURRENT_TEST`` environment variable
|
||||
--------------------------------------------
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
Sometimes a test session might get stuck and there might be no easy way to figure out
|
||||
which test got stuck, for example if pytest was run in quiet mode (``-q``) or you don't have access to the console
|
||||
@@ -935,6 +937,8 @@ like ``pytest-timeout`` they must be imported explicitly and passed on to pytest
|
||||
|
||||
|
||||
This allows you to execute tests using the frozen
|
||||
application with standard ``pytest`` command-line options::
|
||||
application with standard ``pytest`` command-line options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
./app_main --pytest --verbose --tb=long --junitxml=results.xml test-suite/
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import pytest
|
||||
|
||||
xfail = pytest.mark.xfail
|
||||
|
||||
@@ -7,7 +7,7 @@ pytest fixtures: explicit, modular, scalable
|
||||
|
||||
.. currentmodule:: _pytest.python
|
||||
|
||||
.. versionadded:: 2.0/2.3/2.4
|
||||
|
||||
|
||||
.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
|
||||
.. _`purpose of test fixtures`: http://en.wikipedia.org/wiki/Test_fixture#Software
|
||||
@@ -74,7 +74,7 @@ marked ``smtp_connection`` fixture function. Running the test looks like this:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_smtpsimple.py F [100%]
|
||||
@@ -114,7 +114,9 @@ with a list of available function arguments.
|
||||
|
||||
.. note::
|
||||
|
||||
You can always issue ::
|
||||
You can always issue:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --fixtures test_simplefactory.py
|
||||
|
||||
@@ -215,7 +217,7 @@ inspect what is going on and can now run the tests:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_module.py FF [100%]
|
||||
@@ -274,7 +276,7 @@ Finally, the ``class`` scope will invoke the fixture once per test *class*.
|
||||
``package`` scope (experimental)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.7
|
||||
|
||||
|
||||
In pytest 3.7 the ``package`` scope has been introduced. Package-scoped fixtures
|
||||
are finalized when the last test of a *package* finishes.
|
||||
@@ -290,7 +292,7 @@ are finalized when the last test of a *package* finishes.
|
||||
Higher-scoped fixtures are instantiated first
|
||||
---------------------------------------------
|
||||
|
||||
.. versionadded:: 3.5
|
||||
|
||||
|
||||
Within a function request for features, fixture of higher-scopes (such as ``session``) are instantiated first than
|
||||
lower-scoped fixtures (such as ``function`` or ``class``). The relative order of fixtures of same scope follows
|
||||
@@ -362,7 +364,9 @@ The ``print`` and ``smtp.close()`` statements will execute when the last test in
|
||||
the module has finished execution, regardless of the exception status of the
|
||||
tests.
|
||||
|
||||
Let's execute it::
|
||||
Let's execute it:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -s -q --tb=no
|
||||
FFteardown smtp
|
||||
@@ -471,7 +475,9 @@ read an optional server URL from the test module which uses our fixture::
|
||||
|
||||
We use the ``request.module`` attribute to optionally obtain an
|
||||
``smtpserver`` attribute from the test module. If we just execute
|
||||
again, nothing much has changed::
|
||||
again, nothing much has changed:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -s -q --tb=no
|
||||
FFfinalizing <smtplib.SMTP object at 0xdeadbeef> (smtp.gmail.com)
|
||||
@@ -704,7 +710,7 @@ Running the above tests results in the following test IDs being used:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 10 items
|
||||
<Module test_anothersmtp.py>
|
||||
<Function test_showhelo[smtp.gmail.com]>
|
||||
@@ -749,7 +755,7 @@ Running this test will *skip* the invocation of ``data_set`` with value ``2``:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 3 items
|
||||
|
||||
test_fixture_marks.py::test_data[0] PASSED [ 33%]
|
||||
@@ -794,7 +800,7 @@ Here we declare an ``app`` fixture which receives the previously defined
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 2 items
|
||||
|
||||
test_appsetup.py::test_smtp_connection_exists[smtp.gmail.com] PASSED [ 50%]
|
||||
@@ -865,7 +871,7 @@ Let's run the tests in verbose mode and with looking at the print-output:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y -- $PYTHON_PREFIX/bin/python
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collecting ... collected 8 items
|
||||
|
||||
test_module.py::test_0[1] SETUP otherarg 1
|
||||
@@ -1173,6 +1179,8 @@ Given the tests file structure is:
|
||||
|
||||
conftest.py
|
||||
# content of tests/conftest.py
|
||||
import pytest
|
||||
|
||||
@pytest.fixture
|
||||
def username():
|
||||
return 'username'
|
||||
|
||||
@@ -17,11 +17,15 @@ Installation and Getting Started
|
||||
Install ``pytest``
|
||||
----------------------------------------
|
||||
|
||||
1. Run the following command in your command line::
|
||||
1. Run the following command in your command line:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pip install -U pytest
|
||||
|
||||
2. Check that you installed the correct version::
|
||||
2. Check that you installed the correct version:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pytest --version
|
||||
This is pytest version 4.x.y, imported from $PYTHON_PREFIX/lib/python3.6/site-packages/pytest.py
|
||||
@@ -48,7 +52,7 @@ That’s it. You can now execute the test function:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_sample.py F [100%]
|
||||
@@ -79,7 +83,7 @@ Run multiple tests
|
||||
Assert that a certain exception is raised
|
||||
--------------------------------------------------------------
|
||||
|
||||
Use the ``raises`` helper to assert that some code raises an exception::
|
||||
Use the :ref:`raises <assertraises>` helper to assert that some code raises an exception::
|
||||
|
||||
# content of test_sysexit.py
|
||||
import pytest
|
||||
@@ -168,7 +172,9 @@ List the name ``tmpdir`` in the test function signature and ``pytest`` will look
|
||||
|
||||
More info on tmpdir 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::
|
||||
Find out what kind of builtin :ref:`pytest fixtures <fixtures>` exist with the command:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --fixtures # shows builtin and custom fixtures
|
||||
|
||||
|
||||
@@ -7,12 +7,13 @@ Good Integration Practices
|
||||
Install package with pip
|
||||
-------------------------------------------------
|
||||
|
||||
For development, we recommend to use virtualenv_ environments and pip_
|
||||
for installing your application and any dependencies
|
||||
as well as the ``pytest`` package itself. This ensures your code and
|
||||
dependencies are isolated from the system Python installation.
|
||||
For development, we recommend you use venv_ for virtual environments
|
||||
(or virtualenv_ for Python 2.7) and
|
||||
pip_ for installing your application and any dependencies,
|
||||
as well as the ``pytest`` package itself.
|
||||
This ensures your code and dependencies are isolated from your system Python installation.
|
||||
|
||||
First you need to place a ``setup.py`` file in the root of your package with the following minimum content::
|
||||
Next, place a ``setup.py`` file in the root of your package with the following minimum content::
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
@@ -41,8 +42,8 @@ Conventions for Python test discovery
|
||||
* In those directories, search for ``test_*.py`` or ``*_test.py`` files, imported by their `test package name`_.
|
||||
* From those files, collect test items:
|
||||
|
||||
* ``test_`` prefixed test functions or methods outside of class
|
||||
* ``test_`` prefixed test functions or methods inside ``Test`` prefixed test classes (without an ``__init__`` method)
|
||||
* ``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`.
|
||||
|
||||
|
||||
@@ -4,10 +4,121 @@ Historical Notes
|
||||
This page lists features or behavior from previous versions of pytest which have changed over the years. They are
|
||||
kept here as a historical note so users looking at old code can find documentation related to them.
|
||||
|
||||
|
||||
.. _marker-revamp:
|
||||
|
||||
Marker revamp and iteration
|
||||
---------------------------
|
||||
|
||||
.. versionchanged:: 3.6
|
||||
|
||||
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
|
||||
|
||||
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
|
||||
|
||||
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
|
||||
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
|
||||
|
||||
On top of that markers were not accessible in the same way for modules, classes, and functions/methods.
|
||||
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
|
||||
|
||||
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with
|
||||
the initial design, providing the :func:`_pytest.nodes.Node.iter_markers` method to iterate over
|
||||
markers in a consistent manner and reworking the internals, which solved a great deal of problems
|
||||
with the initial design.
|
||||
|
||||
|
||||
.. _update marker code:
|
||||
|
||||
Updating code
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
|
||||
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
|
||||
|
||||
In general there are two scenarios on how markers should be handled:
|
||||
|
||||
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
|
||||
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
|
||||
|
||||
In this case, use ``Node.get_closest_marker(name)``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# replace this:
|
||||
marker = item.get_marker("log_level")
|
||||
if marker:
|
||||
level = marker.args[0]
|
||||
|
||||
# by this:
|
||||
marker = item.get_closest_marker("log_level")
|
||||
if marker:
|
||||
level = marker.args[0]
|
||||
|
||||
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
|
||||
order doesn't even matter. You probably want to think of your marks as a set here.
|
||||
|
||||
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# replace this
|
||||
skipif = item.get_marker("skipif")
|
||||
if skipif:
|
||||
for condition in skipif.args:
|
||||
# eval condition
|
||||
...
|
||||
|
||||
# by this:
|
||||
for skipif in item.iter_markers("skipif"):
|
||||
condition = skipif.args[0]
|
||||
# eval condition
|
||||
|
||||
|
||||
If you are unsure or have any questions, please consider opening
|
||||
`an issue <https://github.com/pytest-dev/pytest/issues>`_.
|
||||
|
||||
Related issues
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Here is a non-exhaustive list of issues fixed by the new implementation:
|
||||
|
||||
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
|
||||
|
||||
* Markers stain on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
|
||||
|
||||
* Combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
|
||||
|
||||
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
|
||||
|
||||
* Marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
|
||||
|
||||
* Fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
|
||||
|
||||
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
|
||||
|
||||
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
|
||||
|
||||
* Remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
|
||||
|
||||
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
|
||||
|
||||
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
|
||||
|
||||
* Marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
|
||||
|
||||
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
in a future major relase of pytest we will introduce class based markers,
|
||||
at which point markers will no longer be limited to instances of :py:class:`Mark`.
|
||||
|
||||
|
||||
cache plugin integrated into the core
|
||||
-------------------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
The functionality of the :ref:`core cache <cache>` plugin was previously distributed
|
||||
as a third party plugin named ``pytest-cache``. The core plugin
|
||||
@@ -18,7 +129,7 @@ can only store/receive data between test runs that is json-serializable.
|
||||
funcargs and ``pytest_funcarg__``
|
||||
---------------------------------
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
|
||||
|
||||
In versions prior to 2.3 there was no ``@pytest.fixture`` marker
|
||||
and you had to use a magic ``pytest_funcarg__NAME`` prefix
|
||||
@@ -30,7 +141,7 @@ functions.
|
||||
``@pytest.yield_fixture`` decorator
|
||||
-----------------------------------
|
||||
|
||||
.. versionchanged:: 2.10
|
||||
|
||||
|
||||
Prior to version 2.10, in order to use a ``yield`` statement to execute teardown code one
|
||||
had to mark a fixture using the ``yield_fixture`` marker. From 2.10 onward, normal
|
||||
@@ -41,7 +152,7 @@ and considered deprecated.
|
||||
``[pytest]`` header in ``setup.cfg``
|
||||
------------------------------------
|
||||
|
||||
.. versionchanged:: 3.0
|
||||
|
||||
|
||||
Prior to 3.0, the supported section name was ``[pytest]``. Due to how
|
||||
this may collide with some distutils commands, the recommended
|
||||
@@ -54,17 +165,19 @@ name is ``[pytest]``.
|
||||
Applying marks to ``@pytest.mark.parametrize`` parameters
|
||||
---------------------------------------------------------
|
||||
|
||||
.. versionchanged:: 3.1
|
||||
|
||||
|
||||
Prior to version 3.1 the supported mechanism for marking values
|
||||
used the syntax::
|
||||
used the syntax:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
@pytest.mark.parametrize("test_input,expected", [
|
||||
("3+5", 8),
|
||||
("2+4", 6),
|
||||
pytest.mark.xfail(("6*9", 42),),
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_input,expected", [("3+5", 8), ("2+4", 6), pytest.mark.xfail(("6*9", 42))]
|
||||
)
|
||||
def test_eval(test_input, expected):
|
||||
assert eval(test_input) == expected
|
||||
|
||||
@@ -78,7 +191,7 @@ The old syntax is planned to be removed in pytest-4.0.
|
||||
``@pytest.mark.parametrize`` argument names as a tuple
|
||||
------------------------------------------------------
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
|
||||
|
||||
In versions prior to 2.4 one needed to specify the argument
|
||||
names as a tuple. This remains valid but the simpler ``"name1,name2,..."``
|
||||
@@ -89,7 +202,7 @@ it's easier to write and produces less line noise.
|
||||
setup: is now an "autouse fixture"
|
||||
----------------------------------
|
||||
|
||||
.. versionchanged:: 2.3
|
||||
|
||||
|
||||
During development prior to the pytest-2.3 release the name
|
||||
``pytest.setup`` was used but before the release it was renamed
|
||||
@@ -102,12 +215,16 @@ namely :ref:`autouse fixtures`
|
||||
Conditions as strings instead of booleans
|
||||
-----------------------------------------
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
|
||||
|
||||
Prior to pytest-2.4 the only way to specify skipif/xfail conditions was
|
||||
to use strings::
|
||||
to use strings:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
@pytest.mark.skipif("sys.version_info >= (3,3)")
|
||||
def test_function():
|
||||
...
|
||||
@@ -139,17 +256,20 @@ dictionary which is constructed as follows:
|
||||
expression is applied.
|
||||
|
||||
The pytest ``config`` object allows you to skip based on a test
|
||||
configuration value which you might have added::
|
||||
configuration value which you might have added:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.skipif("not config.getvalue('db')")
|
||||
def test_function(...):
|
||||
def test_function():
|
||||
...
|
||||
|
||||
The equivalent with "boolean conditions" is::
|
||||
The equivalent with "boolean conditions" is:
|
||||
|
||||
@pytest.mark.skipif(not pytest.config.getvalue("db"),
|
||||
reason="--db was not specified")
|
||||
def test_function(...):
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.skipif(not pytest.config.getvalue("db"), reason="--db was not specified")
|
||||
def test_function():
|
||||
pass
|
||||
|
||||
.. note::
|
||||
@@ -162,14 +282,18 @@ The equivalent with "boolean conditions" is::
|
||||
``pytest.set_trace()``
|
||||
----------------------
|
||||
|
||||
.. versionchanged:: 2.4
|
||||
|
||||
Previous to version 2.4 to set a break point in code one needed to use ``pytest.set_trace()``::
|
||||
|
||||
Previous to version 2.4 to set a break point in code one needed to use ``pytest.set_trace()``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_function():
|
||||
...
|
||||
pytest.set_trace() # invoke PDB debugger and tracing
|
||||
pytest.set_trace() # invoke PDB debugger and tracing
|
||||
|
||||
|
||||
This is no longer needed and one can use the native ``import pdb;pdb.set_trace()`` call directly.
|
||||
@@ -179,7 +303,7 @@ For more details see :ref:`breakpoints`.
|
||||
"compat" properties
|
||||
-------------------
|
||||
|
||||
.. deprecated:: 3.9
|
||||
|
||||
|
||||
Access of ``Module``, ``Function``, ``Class``, ``Instance``, ``File`` and ``Item`` through ``Node`` instances have long
|
||||
been documented as deprecated, but started to emit warnings from pytest ``3.9`` and onward.
|
||||
|
||||
@@ -30,7 +30,7 @@ To execute it:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_sample.py F [100%]
|
||||
|
||||
@@ -5,7 +5,7 @@ License
|
||||
|
||||
Distributed under the terms of the `MIT`_ license, pytest is free and open source software.
|
||||
|
||||
::
|
||||
.. code-block:: text
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
.. _`distribute docs`:
|
||||
.. _`distribute`: https://pypi.org/project/distribute/
|
||||
.. _`pip`: https://pypi.org/project/pip/
|
||||
.. _`venv`: https://docs.python.org/3/library/venv.html/
|
||||
.. _`virtualenv`: https://pypi.org/project/virtualenv/
|
||||
.. _hudson: http://hudson-ci.org/
|
||||
.. _jenkins: http://jenkins-ci.org/
|
||||
|
||||
@@ -3,17 +3,21 @@
|
||||
Logging
|
||||
-------
|
||||
|
||||
.. versionadded:: 3.3
|
||||
.. versionchanged:: 3.4
|
||||
|
||||
|
||||
|
||||
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.
|
||||
|
||||
Running without options::
|
||||
Running without options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest
|
||||
|
||||
Shows failed tests like so::
|
||||
Shows failed tests like so:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
----------------------- Captured stdlog call ----------------------
|
||||
test_reporting.py 26 WARNING text going to logger
|
||||
@@ -27,12 +31,16 @@ By default each captured log message shows the module, line number, log level
|
||||
and message.
|
||||
|
||||
If desired the log and date format can be specified to
|
||||
anything that the logging module supports by passing specific formatting options::
|
||||
anything that the logging module supports by passing specific formatting options:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --log-format="%(asctime)s %(levelname)s %(message)s" \
|
||||
--log-date-format="%Y-%m-%d %H:%M:%S"
|
||||
|
||||
Shows failed tests like so::
|
||||
Shows failed tests like so:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
----------------------- Captured stdlog call ----------------------
|
||||
2010-04-10 14:48:44 WARNING text going to logger
|
||||
@@ -51,7 +59,9 @@ These options can also be customized through ``pytest.ini`` file:
|
||||
log_date_format = %Y-%m-%d %H:%M:%S
|
||||
|
||||
Further it is possible to disable reporting of captured content (stdout,
|
||||
stderr and logs) on failed tests completely with::
|
||||
stderr and logs) on failed tests completely with:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --show-capture=no
|
||||
|
||||
@@ -133,7 +143,6 @@ the records for the ``setup`` and ``call`` stages during teardown like so:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def window(caplog):
|
||||
window = create_window()
|
||||
|
||||
163
doc/en/mark.rst
163
doc/en/mark.rst
@@ -1,9 +1,7 @@
|
||||
|
||||
.. _mark:
|
||||
|
||||
Marking test functions with attributes
|
||||
=================================================================
|
||||
|
||||
======================================
|
||||
|
||||
By using the ``pytest.mark`` helper you can easily set
|
||||
metadata on your test functions. There are
|
||||
@@ -17,8 +15,10 @@ some builtin markers, for example:
|
||||
to the same test function.
|
||||
|
||||
It's easy to create custom markers or to apply markers
|
||||
to whole test classes or modules. See :ref:`mark examples` for examples
|
||||
which also serve as documentation.
|
||||
to whole test classes or modules. Those markers can be used by plugins, and also
|
||||
are commonly used to :ref:`select tests <mark run>` on the command-line with the ``-m`` option.
|
||||
|
||||
See :ref:`mark examples` for examples which also serve as documentation.
|
||||
|
||||
.. note::
|
||||
|
||||
@@ -26,134 +26,53 @@ which also serve as documentation.
|
||||
:ref:`fixtures <fixtures>`.
|
||||
|
||||
|
||||
Raising errors on unknown marks: --strict
|
||||
-----------------------------------------
|
||||
Registering marks
|
||||
-----------------
|
||||
|
||||
When the ``--strict`` command-line flag is passed, any marks not registered in the ``pytest.ini`` file will trigger an error.
|
||||
|
||||
Marks can be registered like this:
|
||||
You can register custom marks in your ``pytest.ini`` file like this:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
markers =
|
||||
slow
|
||||
slow: marks tests as slow (deselect with '-m "not slow"')
|
||||
serial
|
||||
|
||||
This can be used to prevent users mistyping mark names by accident. Test suites that want to enforce this
|
||||
should add ``--strict`` to ``addopts``:
|
||||
Note that everything after the ``:`` is an optional description.
|
||||
|
||||
Alternatively, you can register new markers programatically in a
|
||||
:ref:`pytest_configure <initialization-hooks>` hook:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line(
|
||||
"markers", "env(name): mark test to run only on named environment"
|
||||
)
|
||||
|
||||
|
||||
Registered marks appear in pytest's help text and do not emit warnings (see the next section). It
|
||||
is recommended that third-party plugins always :ref:`register their markers <registering-markers>`.
|
||||
|
||||
.. _unknown-marks:
|
||||
|
||||
Raising errors on unknown marks
|
||||
-------------------------------
|
||||
|
||||
Unregistered marks applied with the ``@pytest.mark.name_of_the_mark`` decorator
|
||||
will always emit a warning in order to avoid silently doing something
|
||||
surprising due to mis-typed names. As described in the previous section, you can disable
|
||||
the warning for custom marks by registering them in your ``pytest.ini`` file or
|
||||
using a custom ``pytest_configure`` hook.
|
||||
|
||||
When the ``--strict-markers`` command-line flag is passed, any unknown marks applied
|
||||
with the ``@pytest.mark.name_of_the_mark`` decorator will trigger an error. You can
|
||||
enforce this validation in your project by adding ``--strict-markers`` to ``addopts``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
addopts = --strict
|
||||
addopts = --strict-markers
|
||||
markers =
|
||||
slow
|
||||
slow: marks tests as slow (deselect with '-m "not slow"')
|
||||
serial
|
||||
|
||||
|
||||
.. _marker-revamp:
|
||||
|
||||
Marker revamp and iteration
|
||||
---------------------------
|
||||
|
||||
.. versionadded:: 3.6
|
||||
|
||||
pytest's marker implementation traditionally worked by simply updating the ``__dict__`` attribute of functions to cumulatively add markers. As a result, markers would unintentionally be passed along class hierarchies in surprising ways. Further, the API for retrieving them was inconsistent, as markers from parameterization would be stored differently than markers applied using the ``@pytest.mark`` decorator and markers added via ``node.add_marker``.
|
||||
|
||||
This state of things made it technically next to impossible to use data from markers correctly without having a deep understanding of the internals, leading to subtle and hard to understand bugs in more advanced usages.
|
||||
|
||||
Depending on how a marker got declared/changed one would get either a ``MarkerInfo`` which might contain markers from sibling classes,
|
||||
``MarkDecorators`` when marks came from parameterization or from a ``node.add_marker`` call, discarding prior marks. Also ``MarkerInfo`` acts like a single mark, when it in fact represents a merged view on multiple marks with the same name.
|
||||
|
||||
On top of that markers were not accessible the same way for modules, classes, and functions/methods.
|
||||
In fact, markers were only accessible in functions, even if they were declared on classes/modules.
|
||||
|
||||
A new API to access markers has been introduced in pytest 3.6 in order to solve the problems with the initial design, providing :func:`_pytest.nodes.Node.iter_markers` method to iterate over markers in a consistent manner and reworking the internals, which solved great deal of problems with the initial design.
|
||||
|
||||
|
||||
.. _update marker code:
|
||||
|
||||
Updating code
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
The old ``Node.get_marker(name)`` function is considered deprecated because it returns an internal ``MarkerInfo`` object
|
||||
which contains the merged name, ``*args`` and ``**kwargs`` of all the markers which apply to that node.
|
||||
|
||||
In general there are two scenarios on how markers should be handled:
|
||||
|
||||
1. Marks overwrite each other. Order matters but you only want to think of your mark as a single item. E.g.
|
||||
``log_level('info')`` at a module level can be overwritten by ``log_level('debug')`` for a specific test.
|
||||
|
||||
In this case, use ``Node.get_closest_marker(name)``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# replace this:
|
||||
marker = item.get_marker("log_level")
|
||||
if marker:
|
||||
level = marker.args[0]
|
||||
|
||||
# by this:
|
||||
marker = item.get_closest_marker("log_level")
|
||||
if marker:
|
||||
level = marker.args[0]
|
||||
|
||||
2. Marks compose in an additive manner. E.g. ``skipif(condition)`` marks mean you just want to evaluate all of them,
|
||||
order doesn't even matter. You probably want to think of your marks as a set here.
|
||||
|
||||
In this case iterate over each mark and handle their ``*args`` and ``**kwargs`` individually.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# replace this
|
||||
skipif = item.get_marker("skipif")
|
||||
if skipif:
|
||||
for condition in skipif.args:
|
||||
# eval condition
|
||||
...
|
||||
|
||||
# by this:
|
||||
for skipif in item.iter_markers("skipif"):
|
||||
condition = skipif.args[0]
|
||||
# eval condition
|
||||
|
||||
|
||||
If you are unsure or have any questions, please consider opening
|
||||
`an issue <https://github.com/pytest-dev/pytest/issues>`_.
|
||||
|
||||
Related issues
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Here is a non-exhaustive list of issues fixed by the new implementation:
|
||||
|
||||
* Marks don't pick up nested classes (`#199 <https://github.com/pytest-dev/pytest/issues/199>`_).
|
||||
|
||||
* Markers stain on all related classes (`#568 <https://github.com/pytest-dev/pytest/issues/568>`_).
|
||||
|
||||
* Combining marks - args and kwargs calculation (`#2897 <https://github.com/pytest-dev/pytest/issues/2897>`_).
|
||||
|
||||
* ``request.node.get_marker('name')`` returns ``None`` for markers applied in classes (`#902 <https://github.com/pytest-dev/pytest/issues/902>`_).
|
||||
|
||||
* Marks applied in parametrize are stored as markdecorator (`#2400 <https://github.com/pytest-dev/pytest/issues/2400>`_).
|
||||
|
||||
* Fix marker interaction in a backward incompatible way (`#1670 <https://github.com/pytest-dev/pytest/issues/1670>`_).
|
||||
|
||||
* Refactor marks to get rid of the current "marks transfer" mechanism (`#2363 <https://github.com/pytest-dev/pytest/issues/2363>`_).
|
||||
|
||||
* Introduce FunctionDefinition node, use it in generate_tests (`#2522 <https://github.com/pytest-dev/pytest/issues/2522>`_).
|
||||
|
||||
* Remove named marker attributes and collect markers in items (`#891 <https://github.com/pytest-dev/pytest/issues/891>`_).
|
||||
|
||||
* skipif mark from parametrize hides module level skipif mark (`#1540 <https://github.com/pytest-dev/pytest/issues/1540>`_).
|
||||
|
||||
* skipif + parametrize not skipping tests (`#1296 <https://github.com/pytest-dev/pytest/issues/1296>`_).
|
||||
|
||||
* Marker transfer incompatible with inheritance (`#535 <https://github.com/pytest-dev/pytest/issues/535>`_).
|
||||
|
||||
More details can be found in the `original PR <https://github.com/pytest-dev/pytest/pull/3317>`_.
|
||||
|
||||
.. note::
|
||||
|
||||
in a future major relase of pytest we will introduce class based markers,
|
||||
at which point markers will no longer be limited to instances of :py:class:`Mark`
|
||||
|
||||
@@ -16,7 +16,7 @@ and a discussion of its motivation.
|
||||
|
||||
|
||||
Simple example: monkeypatching functions
|
||||
---------------------------------------------------
|
||||
----------------------------------------
|
||||
|
||||
If you want to pretend that ``os.expanduser`` returns a certain
|
||||
directory, you can use the :py:meth:`monkeypatch.setattr` method to
|
||||
@@ -38,8 +38,8 @@ Here our test function monkeypatches ``os.path.expanduser`` and
|
||||
then calls into a function that calls it. After the test function
|
||||
finishes the ``os.path.expanduser`` modification will be undone.
|
||||
|
||||
example: preventing "requests" from remote operations
|
||||
------------------------------------------------------
|
||||
Global patch example: preventing "requests" from remote operations
|
||||
------------------------------------------------------------------
|
||||
|
||||
If you want to prevent the "requests" library from performing http
|
||||
requests in all your tests, you can do::
|
||||
@@ -81,6 +81,80 @@ so that any attempts within tests to create http requests will fail.
|
||||
See issue `#3290 <https://github.com/pytest-dev/pytest/issues/3290>`_ for details.
|
||||
|
||||
|
||||
Monkeypatching environment variables
|
||||
------------------------------------
|
||||
|
||||
If you are working with environment variables you often need to safely change the values
|
||||
or delete them from the system for testing purposes. ``Monkeypatch`` provides a mechanism
|
||||
to do this using the ``setenv`` and ``delenv`` method. Our example code to test:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# contents of our original code file e.g. code.py
|
||||
import os
|
||||
|
||||
|
||||
def get_os_user_lower():
|
||||
"""Simple retrieval function.
|
||||
Returns lowercase USER or raises EnvironmentError."""
|
||||
username = os.getenv("USER")
|
||||
|
||||
if username is None:
|
||||
raise EnvironmentError("USER environment is not set.")
|
||||
|
||||
return username.lower()
|
||||
|
||||
There are two potential paths. First, the ``USER`` environment variable is set to a
|
||||
value. Second, the ``USER`` environment variable does not exist. Using ``monkeypatch``
|
||||
both paths can be safely tested without impacting the running environment:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# contents of our test file e.g. test_code.py
|
||||
import pytest
|
||||
|
||||
|
||||
def test_upper_to_lower(monkeypatch):
|
||||
"""Set the USER env var to assert the behavior."""
|
||||
monkeypatch.setenv("USER", "TestingUser")
|
||||
assert get_os_user_lower() == "testinguser"
|
||||
|
||||
|
||||
def test_raise_exception(monkeypatch):
|
||||
"""Remove the USER env var and assert EnvironmentError is raised."""
|
||||
monkeypatch.delenv("USER", raising=False)
|
||||
|
||||
with pytest.raises(EnvironmentError):
|
||||
_ = get_os_user_lower()
|
||||
|
||||
This behavior can be moved into ``fixture`` structures and shared across tests:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_env_user(monkeypatch):
|
||||
monkeypatch.setenv("USER", "TestingUser")
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mock_env_missing(monkeypatch):
|
||||
monkeypatch.delenv("USER", raising=False)
|
||||
|
||||
|
||||
# Notice the tests reference the fixtures for mocks
|
||||
def test_upper_to_lower(mock_env_user):
|
||||
assert get_os_user_lower() == "testinguser"
|
||||
|
||||
|
||||
def test_raise_exception(mock_env_missing):
|
||||
with pytest.raises(EnvironmentError):
|
||||
_ = get_os_user_lower()
|
||||
|
||||
|
||||
|
||||
.. currentmodule:: _pytest.monkeypatch
|
||||
|
||||
API Reference
|
||||
|
||||
@@ -12,7 +12,9 @@ Running tests written for nose
|
||||
Usage
|
||||
-------------
|
||||
|
||||
After :ref:`installation` type::
|
||||
After :ref:`installation` type:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
python setup.py develop # make sure tests can import our package
|
||||
pytest # instead of 'nosetests'
|
||||
|
||||
@@ -29,22 +29,22 @@ pytest enables test parametrization at several levels:
|
||||
|
||||
.. regendoc: wipe
|
||||
|
||||
.. versionadded:: 2.2
|
||||
.. versionchanged:: 2.4
|
||||
|
||||
|
||||
Several improvements.
|
||||
|
||||
The builtin :ref:`pytest.mark.parametrize ref` decorator enables
|
||||
parametrization of arguments for a test function. Here is a typical example
|
||||
of a test function that implements checking that a certain input leads
|
||||
to an expected output::
|
||||
to an expected output:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_expectation.py
|
||||
import pytest
|
||||
@pytest.mark.parametrize("test_input,expected", [
|
||||
("3+5", 8),
|
||||
("2+4", 6),
|
||||
("6*9", 42),
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
|
||||
def test_eval(test_input, expected):
|
||||
assert eval(test_input) == expected
|
||||
|
||||
@@ -58,7 +58,7 @@ them in turn:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..F [100%]
|
||||
@@ -68,19 +68,30 @@ them in turn:
|
||||
|
||||
test_input = '6*9', expected = 42
|
||||
|
||||
@pytest.mark.parametrize("test_input,expected", [
|
||||
("3+5", 8),
|
||||
("2+4", 6),
|
||||
("6*9", 42),
|
||||
])
|
||||
@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
|
||||
def test_eval(test_input, expected):
|
||||
> assert eval(test_input) == expected
|
||||
E AssertionError: assert 54 == 42
|
||||
E + where 54 = eval('6*9')
|
||||
|
||||
test_expectation.py:8: AssertionError
|
||||
test_expectation.py:6: AssertionError
|
||||
==================== 1 failed, 2 passed in 0.12 seconds ====================
|
||||
|
||||
.. note::
|
||||
|
||||
pytest by default escapes any non-ascii characters used in unicode strings
|
||||
for the parametrization because it has several downsides.
|
||||
If however you would like to use unicode strings in parametrization and see them in the terminal as is (non-escaped), use this option in your ``pytest.ini``:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True
|
||||
|
||||
Keep in mind however that this might cause unwanted side effects and
|
||||
even bugs depending on the OS used and plugins currently installed, so use it at your own risk.
|
||||
|
||||
|
||||
As designed in this example, only one pair of input/output values fails
|
||||
the simple test function. And as usual with test function arguments,
|
||||
you can see the ``input`` and ``output`` values in the traceback.
|
||||
@@ -89,16 +100,18 @@ Note that you could also use the parametrize marker on a class or a module
|
||||
(see :ref:`mark`) which would invoke several functions with the argument sets.
|
||||
|
||||
It is also possible to mark individual test instances within parametrize,
|
||||
for example with the builtin ``mark.xfail``::
|
||||
for example with the builtin ``mark.xfail``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_expectation.py
|
||||
import pytest
|
||||
@pytest.mark.parametrize("test_input,expected", [
|
||||
("3+5", 8),
|
||||
("2+4", 6),
|
||||
pytest.param("6*9", 42,
|
||||
marks=pytest.mark.xfail),
|
||||
])
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"test_input,expected",
|
||||
[("3+5", 8), ("2+4", 6), pytest.param("6*9", 42, marks=pytest.mark.xfail)],
|
||||
)
|
||||
def test_eval(test_input, expected):
|
||||
assert eval(test_input) == expected
|
||||
|
||||
@@ -110,7 +123,7 @@ Let's run this:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 3 items
|
||||
|
||||
test_expectation.py ..x [100%]
|
||||
@@ -125,9 +138,13 @@ example, if they're dynamically generated by some function - the behaviour of
|
||||
pytest is defined by the :confval:`empty_parameter_set_mark` option.
|
||||
|
||||
To get all combinations of multiple parametrized arguments you can stack
|
||||
``parametrize`` decorators::
|
||||
``parametrize`` decorators:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.mark.parametrize("x", [0, 1])
|
||||
@pytest.mark.parametrize("y", [2, 3])
|
||||
def test_foo(x, y):
|
||||
@@ -151,28 +168,40 @@ parametrization.
|
||||
|
||||
For example, let's say we want to run a test taking string inputs which
|
||||
we want to set via a new ``pytest`` command line option. Let's first write
|
||||
a simple test accepting a ``stringinput`` fixture function argument::
|
||||
a simple test accepting a ``stringinput`` fixture function argument:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_strings.py
|
||||
|
||||
|
||||
def test_valid_string(stringinput):
|
||||
assert stringinput.isalpha()
|
||||
|
||||
Now we add a ``conftest.py`` file containing the addition of a
|
||||
command line option and the parametrization of our test function::
|
||||
command line option and the parametrization of our test function:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of conftest.py
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption("--stringinput", action="append", default=[],
|
||||
help="list of stringinputs to pass to test functions")
|
||||
parser.addoption(
|
||||
"--stringinput",
|
||||
action="append",
|
||||
default=[],
|
||||
help="list of stringinputs to pass to test functions",
|
||||
)
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc):
|
||||
if 'stringinput' in metafunc.fixturenames:
|
||||
metafunc.parametrize("stringinput",
|
||||
metafunc.config.getoption('stringinput'))
|
||||
if "stringinput" in metafunc.fixturenames:
|
||||
metafunc.parametrize("stringinput", metafunc.config.getoption("stringinput"))
|
||||
|
||||
If we now pass two stringinput values, our test will run twice::
|
||||
If we now pass two stringinput values, our test will run twice:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ pytest -q --stringinput="hello" --stringinput="world" test_strings.py
|
||||
.. [100%]
|
||||
@@ -195,7 +224,7 @@ Let's also run with a stringinput that will lead to a failing test:
|
||||
E + where False = <built-in method isalpha of str object at 0xdeadbeef>()
|
||||
E + where <built-in method isalpha of str object at 0xdeadbeef> = '!'.isalpha
|
||||
|
||||
test_strings.py:3: AssertionError
|
||||
test_strings.py:4: AssertionError
|
||||
1 failed in 0.12 seconds
|
||||
|
||||
As expected our test function fails.
|
||||
@@ -209,7 +238,7 @@ list:
|
||||
$ pytest -q -rs test_strings.py
|
||||
s [100%]
|
||||
========================= short test summary info ==========================
|
||||
SKIPPED [1] test_strings.py: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:1
|
||||
SKIPPED [1] test_strings.py: got empty parameter set ['stringinput'], function test_valid_string at $REGENDOC_TMPDIR/test_strings.py:2
|
||||
1 skipped in 0.12 seconds
|
||||
|
||||
Note that when calling ``metafunc.parametrize`` multiple times with different parameter sets, all parameter names across
|
||||
|
||||
@@ -27,7 +27,7 @@ Here is a little annotated list for some popular plugins:
|
||||
for `twisted <http://twistedmatrix.com>`_ apps, starting a reactor and
|
||||
processing deferreds from test functions.
|
||||
|
||||
* `pytest-cov <https://pypi.org/project/pytest-cov/>`_:
|
||||
* `pytest-cov <https://pypi.org/project/pytest-cov/>`__:
|
||||
coverage reporting, compatible with distributed testing
|
||||
|
||||
* `pytest-xdist <https://pypi.org/project/pytest-xdist/>`_:
|
||||
|
||||
@@ -7,16 +7,20 @@ Python 3.4's last release is scheduled for
|
||||
`March 2019 <https://www.python.org/dev/peps/pep-0429/#release-schedule>`__. pytest is one of
|
||||
the participating projects of the https://python3statement.org.
|
||||
|
||||
We plan to drop support for Python 2.7 and 3.4 at the same time with the release of **pytest 5.0**,
|
||||
scheduled to be released by **mid-2019**. Thanks to the `python_requires <https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires>`__ ``setuptools`` option,
|
||||
The **pytest 4.6** series will be the last to support Python 2.7 and 3.4, and is scheduled
|
||||
to be released by **mid-2019**. **pytest 5.0** and onwards will support only Python 3.5+.
|
||||
|
||||
Thanks to the `python_requires`_ ``setuptools`` option,
|
||||
Python 2.7 and Python 3.4 users using a modern ``pip`` version
|
||||
will install the last compatible pytest ``4.X`` version automatically even if ``5.0`` or later
|
||||
will install the last pytest ``4.6`` version automatically even if ``5.0`` or later
|
||||
are available on PyPI.
|
||||
|
||||
During the period **from mid-2019 and 2020**, the pytest core team plans to make
|
||||
bug-fix releases of the pytest ``4.X`` series by back-porting patches to the ``4.x-maintenance``
|
||||
branch.
|
||||
While pytest ``5.0`` will be the new mainstream and development version, until **January 2020**
|
||||
the pytest core team plans to make bug-fix releases of the pytest ``4.6`` series by
|
||||
back-porting patches to the ``4.6-maintenance`` branch that affect Python 2 users.
|
||||
|
||||
**After 2020**, the core team will no longer actively back port-patches, but the ``4.x-maintenance``
|
||||
branch will continue to exist so the community itself can contribute patches. The
|
||||
core team will be happy to accept those patches and make new ``4.X`` releases **until mid-2020**.
|
||||
**After 2020**, the core team will no longer actively backport patches, but the ``4.6-maintenance``
|
||||
branch will continue to exist so the community itself can contribute patches. The core team will
|
||||
be happy to accept those patches and make new ``4.6`` releases **until mid-2020**.
|
||||
|
||||
.. _`python_requires`: https://packaging.python.org/guides/distributing-packages-using-setuptools/#python-requires>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
Reference
|
||||
=========
|
||||
|
||||
@@ -49,7 +48,7 @@ pytest.main
|
||||
.. autofunction:: _pytest.config.main
|
||||
|
||||
pytest.param
|
||||
~~~~~~~~~~~~~
|
||||
~~~~~~~~~~~~
|
||||
|
||||
.. autofunction:: pytest.param(*values, [id], [marks])
|
||||
|
||||
@@ -199,16 +198,18 @@ Marks a test function as *expected to fail*.
|
||||
.. py:function:: pytest.mark.xfail(condition=None, *, reason=None, raises=None, run=True, strict=False)
|
||||
|
||||
:type condition: bool or str
|
||||
:param condition: ``True/False`` if the condition should be marked as xfail or a :ref:`condition string <string conditions>`.
|
||||
:param condition:
|
||||
Condition for marking the test function as xfail (``True/False`` or a
|
||||
:ref:`condition string <string conditions>`).
|
||||
:keyword str reason: Reason why the test function is marked as xfail.
|
||||
:keyword Exception raises: Exception subclass expected to be raised by the test function; other exceptions will fail the test.
|
||||
:keyword bool run:
|
||||
If the test function should actually be executed. If ``False``, the function will always xfail and will
|
||||
not be executed (useful a function is segfaulting).
|
||||
not be executed (useful if a function is segfaulting).
|
||||
:keyword bool strict:
|
||||
* If ``False`` (the default) the function will be shown in the terminal output as ``xfailed`` if it fails
|
||||
and as ``xpass`` if it passes. In both cases this will not cause the test suite to fail as a whole. This
|
||||
is particularly useful to mark *flaky* tests (tests that random at fail) to be tackled later.
|
||||
is particularly useful to mark *flaky* tests (tests that fail at random) to be tackled later.
|
||||
* If ``True``, the function will be shown in the terminal output as ``xfailed`` if it fails, but if it
|
||||
unexpectedly passes then it will **fail** the test suite. This is particularly useful to mark functions
|
||||
that are always failing and there should be a clear indication if they unexpectedly start to pass (for example
|
||||
@@ -423,6 +424,14 @@ record_property
|
||||
|
||||
.. autofunction:: _pytest.junitxml.record_property()
|
||||
|
||||
|
||||
record_testsuite_property
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
**Tutorial**: :ref:`record_testsuite_property example`.
|
||||
|
||||
.. autofunction:: _pytest.junitxml.record_testsuite_property()
|
||||
|
||||
caplog
|
||||
~~~~~~
|
||||
|
||||
@@ -499,6 +508,32 @@ Each recorded warning is an instance of :class:`warnings.WarningMessage`.
|
||||
differently; see :ref:`ensuring_function_triggers`.
|
||||
|
||||
|
||||
tmp_path
|
||||
~~~~~~~~
|
||||
|
||||
**Tutorial**: :doc:`tmpdir`
|
||||
|
||||
.. currentmodule:: _pytest.tmpdir
|
||||
|
||||
.. autofunction:: tmp_path()
|
||||
:no-auto-options:
|
||||
|
||||
|
||||
tmp_path_factory
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
**Tutorial**: :ref:`tmp_path_factory example`
|
||||
|
||||
.. _`tmp_path_factory factory api`:
|
||||
|
||||
``tmp_path_factory`` instances have the following methods:
|
||||
|
||||
.. currentmodule:: _pytest.tmpdir
|
||||
|
||||
.. automethod:: TempPathFactory.mktemp
|
||||
.. automethod:: TempPathFactory.getbasetemp
|
||||
|
||||
|
||||
tmpdir
|
||||
~~~~~~
|
||||
|
||||
@@ -546,6 +581,8 @@ Bootstrapping hooks called for plugins registered early enough (internal and set
|
||||
.. autofunction:: pytest_cmdline_parse
|
||||
.. autofunction:: pytest_cmdline_main
|
||||
|
||||
.. _`initialization-hooks`:
|
||||
|
||||
Initialization hooks
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -558,6 +595,8 @@ Initialization hooks called for plugins and ``conftest.py`` files.
|
||||
.. autofunction:: pytest_sessionstart
|
||||
.. autofunction:: pytest_sessionfinish
|
||||
|
||||
.. autofunction:: pytest_plugin_registered
|
||||
|
||||
Test running hooks
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -581,6 +620,8 @@ into interactive debugging when a test failure occurs.
|
||||
The :py:mod:`_pytest.terminal` reported specifically uses
|
||||
the reporting hook to print information about a test run.
|
||||
|
||||
.. autofunction:: pytest_pyfunc_call
|
||||
|
||||
Collection hooks
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
@@ -590,6 +631,7 @@ Collection hooks
|
||||
.. autofunction:: pytest_ignore_collect
|
||||
.. autofunction:: pytest_collect_directory
|
||||
.. autofunction:: pytest_collect_file
|
||||
.. autofunction:: pytest_pycollect_makemodule
|
||||
|
||||
For influencing the collection of objects in Python modules
|
||||
you can use the following hook:
|
||||
@@ -603,12 +645,15 @@ items, delete or otherwise amend the test items:
|
||||
|
||||
.. autofunction:: pytest_collection_modifyitems
|
||||
|
||||
.. autofunction:: pytest_collection_finish
|
||||
|
||||
Reporting hooks
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
Session related reporting hooks:
|
||||
|
||||
.. autofunction:: pytest_collectstart
|
||||
.. autofunction:: pytest_make_collect_report
|
||||
.. autofunction:: pytest_itemcollected
|
||||
.. autofunction:: pytest_collectreport
|
||||
.. autofunction:: pytest_deselected
|
||||
@@ -847,7 +892,7 @@ pytest_mark
|
||||
**Tutorial**: :ref:`scoped-marking`
|
||||
|
||||
Can be declared at the **global** level in *test modules* to apply one or more :ref:`marks <marks ref>` to all
|
||||
test functions and methods. Can be either a single mark or a sequence of marks.
|
||||
test functions and methods. Can be either a single mark or a list of marks.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
@@ -860,7 +905,7 @@ test functions and methods. Can be either a single mark or a sequence of marks.
|
||||
|
||||
import pytest
|
||||
|
||||
pytestmark = (pytest.mark.integration, pytest.mark.slow)
|
||||
pytestmark = [pytest.mark.integration, pytest.mark.slow]
|
||||
|
||||
PYTEST_DONT_REWRITE (module docstring)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -948,7 +993,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: cache_dir
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
Sets a directory where stores content of cache plugin. Default directory is
|
||||
``.pytest_cache`` which is created in :ref:`rootdir <rootdir>`. Directory may be
|
||||
@@ -968,7 +1013,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: console_output_style
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets the console output style while running tests:
|
||||
|
||||
@@ -988,7 +1033,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: doctest_encoding
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
Default encoding to use to decode text files with docstrings.
|
||||
:doc:`See how pytest handles doctests <doctest>`.
|
||||
@@ -1002,7 +1047,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: empty_parameter_set_mark
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
Allows to pick the action for empty parametersets in parameterization
|
||||
|
||||
@@ -1025,7 +1070,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: filterwarnings
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
Sets a list of filters and actions that should be taken for matched
|
||||
warnings. By default all warnings emitted during the test session
|
||||
@@ -1042,6 +1087,22 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
This tells pytest to ignore deprecation warnings and turn all other warnings
|
||||
into errors. For more information please refer to :ref:`warnings`.
|
||||
|
||||
|
||||
.. confval:: junit_duration_report
|
||||
|
||||
.. versionadded:: 4.1
|
||||
|
||||
Configures how durations are recorded into the JUnit XML report:
|
||||
|
||||
* ``total`` (the default): duration times reported include setup, call, and teardown times.
|
||||
* ``call``: duration times reported include only call times, excluding setup and teardown.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
junit_duration_report = call
|
||||
|
||||
|
||||
.. confval:: junit_family
|
||||
|
||||
.. versionadded:: 4.2
|
||||
@@ -1057,9 +1118,34 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
[pytest]
|
||||
junit_family = xunit2
|
||||
|
||||
.. confval:: junit_suite_name
|
||||
|
||||
.. versionadded:: 3.1
|
||||
.. confval:: junit_logging
|
||||
|
||||
.. versionadded:: 3.5
|
||||
|
||||
Configures if stdout/stderr should be written to the JUnit XML file. Valid values are
|
||||
``system-out``, ``system-err``, and ``no`` (the default).
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
junit_logging = system-out
|
||||
|
||||
|
||||
.. confval:: junit_log_passing_tests
|
||||
|
||||
.. versionadded:: 4.6
|
||||
|
||||
If ``junit_logging != "no"``, configures if the captured output should be written
|
||||
to the JUnit XML file for **passing** tests. Default is ``True``.
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
junit_log_passing_tests = False
|
||||
|
||||
|
||||
.. confval:: junit_suite_name
|
||||
|
||||
To set the name of the root test suite xml item, you can configure the ``junit_suite_name`` option in your config file:
|
||||
|
||||
@@ -1071,7 +1157,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_cli_date_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:func:`time.strftime`-compatible string that will be used when formatting dates for live logging.
|
||||
|
||||
@@ -1084,7 +1170,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_cli_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:mod:`logging`-compatible string used to format live logging messages.
|
||||
|
||||
@@ -1098,7 +1184,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_cli_level
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets the minimum log message level that should be captured for live logging. The integer value or
|
||||
the names of the levels can be used.
|
||||
@@ -1113,7 +1199,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_date_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:func:`time.strftime`-compatible string that will be used when formatting dates for logging capture.
|
||||
|
||||
@@ -1127,7 +1213,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_file
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a file name relative to the ``pytest.ini`` file where log messages should be written to, in addition
|
||||
to the other logging facilities that are active.
|
||||
@@ -1142,7 +1228,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_file_date_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:func:`time.strftime`-compatible string that will be used when formatting dates for the logging file.
|
||||
|
||||
@@ -1155,7 +1241,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_file_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:mod:`logging`-compatible string used to format logging messages redirected to the logging file.
|
||||
|
||||
@@ -1168,7 +1254,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_file_level
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets the minimum log message level that should be captured for the logging file. The integer value or
|
||||
the names of the levels can be used.
|
||||
@@ -1183,7 +1269,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_format
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets a :py:mod:`logging`-compatible string used to format captured logging messages.
|
||||
|
||||
@@ -1197,7 +1283,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_level
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
Sets the minimum log message level that should be captured for logging capture. The integer value or
|
||||
the names of the levels can be used.
|
||||
@@ -1212,7 +1298,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: log_print
|
||||
|
||||
.. versionadded:: 3.3
|
||||
|
||||
|
||||
If set to ``False``, will disable displaying captured logging messages for failed tests.
|
||||
|
||||
@@ -1226,12 +1312,17 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: markers
|
||||
|
||||
List of markers that are allowed in test functions, enforced when ``--strict`` command-line argument is used.
|
||||
You can use a marker name per line, indented from the option name.
|
||||
When the ``--strict-markers`` or ``--strict`` command-line arguments are used,
|
||||
only known markers - defined in code by core pytest or some plugin - are allowed.
|
||||
|
||||
You can list additional markers in this setting to add them to the whitelist,
|
||||
in which case you probably want to add ``--strict-markers`` to ``addopts``
|
||||
to avoid future regressions:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[pytest]
|
||||
addopts = --strict-markers
|
||||
markers =
|
||||
slow
|
||||
serial
|
||||
@@ -1346,7 +1437,7 @@ passed multiple times. The expected format is ``name=value``. For example::
|
||||
|
||||
.. confval:: testpaths
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
Sets list of directories that should be searched for tests when
|
||||
no specific directories, files or test ids are given in the command line when
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
pygments-pytest>=1.1.0
|
||||
sphinx>=1.8.2
|
||||
sphinx>=1.8.2,<2.1
|
||||
sphinxcontrib-trio
|
||||
sphinx-removed-in>=0.1.3
|
||||
sphinx-removed-in>=0.2.0
|
||||
|
||||
@@ -22,7 +22,9 @@ it's an **xpass** and will be reported in the test summary.
|
||||
``pytest`` counts and lists *skip* and *xfail* tests separately. Detailed
|
||||
information about skipped/xfailed tests is not shown by default to avoid
|
||||
cluttering the output. You can use the ``-r`` option to see details
|
||||
corresponding to the "short" letters shown in the test progress::
|
||||
corresponding to the "short" letters shown in the test progress:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -rxXs # show extra info on xfailed, xpassed, and skipped tests
|
||||
|
||||
@@ -37,7 +39,7 @@ More details on the ``-r`` option can be found by running ``pytest -h``.
|
||||
Skipping test functions
|
||||
-----------------------
|
||||
|
||||
.. versionadded:: 2.9
|
||||
|
||||
|
||||
The simplest way to skip a test function is to mark it with the ``skip`` decorator
|
||||
which may be passed an optional ``reason``:
|
||||
@@ -78,36 +80,48 @@ It is also possible to skip the whole module using
|
||||
``skipif``
|
||||
~~~~~~~~~~
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
|
||||
If you wish to skip something conditionally then you can use ``skipif`` instead.
|
||||
Here is an example of marking a test function to be skipped
|
||||
when run on an interpreter earlier than Python3.6 ::
|
||||
when run on an interpreter earlier than Python3.6:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import sys
|
||||
@pytest.mark.skipif(sys.version_info < (3,6),
|
||||
reason="requires python3.6 or higher")
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires python3.6 or higher")
|
||||
def test_function():
|
||||
...
|
||||
|
||||
If the condition evaluates to ``True`` during collection, the test function will be skipped,
|
||||
with the specified reason appearing in the summary when using ``-rs``.
|
||||
|
||||
You can share ``skipif`` markers between modules. Consider this test module::
|
||||
You can share ``skipif`` markers between modules. Consider this test module:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_mymodule.py
|
||||
import mymodule
|
||||
minversion = pytest.mark.skipif(mymodule.__versioninfo__ < (1,1),
|
||||
reason="at least mymodule-1.1 required")
|
||||
|
||||
minversion = pytest.mark.skipif(
|
||||
mymodule.__versioninfo__ < (1, 1), reason="at least mymodule-1.1 required"
|
||||
)
|
||||
|
||||
|
||||
@minversion
|
||||
def test_function():
|
||||
...
|
||||
|
||||
You can import the marker and reuse it in another test module::
|
||||
You can import the marker and reuse it in another test module:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# test_myothermodule.py
|
||||
from test_mymodule import minversion
|
||||
|
||||
|
||||
@minversion
|
||||
def test_anotherfunction():
|
||||
...
|
||||
@@ -126,12 +140,12 @@ so they are supported mainly for backward compatibility reasons.
|
||||
Skip all test functions of a class or module
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You can use the ``skipif`` marker (as any other marker) on classes::
|
||||
You can use the ``skipif`` marker (as any other marker) on classes:
|
||||
|
||||
@pytest.mark.skipif(sys.platform == 'win32',
|
||||
reason="does not run on windows")
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32", reason="does not run on windows")
|
||||
class TestPosixCalls(object):
|
||||
|
||||
def test_function(self):
|
||||
"will not be setup or run under 'win32' platform"
|
||||
|
||||
@@ -194,7 +208,7 @@ Here's a quick guide on how to skip tests in a module in different situations:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
pytestmark = pytest.mark.skipif(sys.platform == "win32", "tests for linux only")
|
||||
pytestmark = pytest.mark.skipif(sys.platform == "win32", reason="tests for linux only")
|
||||
|
||||
3. Skip all tests in a module if some import is missing:
|
||||
|
||||
@@ -240,7 +254,7 @@ internally by raising a known exception.
|
||||
``strict`` parameter
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
.. versionadded:: 2.9
|
||||
|
||||
|
||||
Both ``XFAIL`` and ``XPASS`` don't fail the test suite, unless the ``strict`` keyword-only
|
||||
parameter is passed as ``True``:
|
||||
@@ -267,10 +281,11 @@ You can change the default value of the ``strict`` parameter using the
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
As with skipif_ you can also mark your expectation of a failure
|
||||
on a particular platform::
|
||||
on a particular platform:
|
||||
|
||||
@pytest.mark.xfail(sys.version_info >= (3,6),
|
||||
reason="python3.6 api changes")
|
||||
.. code-block:: python
|
||||
|
||||
@pytest.mark.xfail(sys.version_info >= (3, 6), reason="python3.6 api changes")
|
||||
def test_function():
|
||||
...
|
||||
|
||||
@@ -309,7 +324,9 @@ investigated later.
|
||||
Ignoring xfail
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
By specifying on the commandline::
|
||||
By specifying on the commandline:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --runxfail
|
||||
|
||||
@@ -331,10 +348,11 @@ Running it with the report-on-xfail option gives this output:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR/example, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR/example
|
||||
collected 7 items
|
||||
|
||||
xfail_demo.py xxxxxxx [100%]
|
||||
|
||||
========================= short test summary info ==========================
|
||||
XFAIL xfail_demo.py::test_hello
|
||||
XFAIL xfail_demo.py::test_hello2
|
||||
@@ -348,7 +366,6 @@ Running it with the report-on-xfail option gives this output:
|
||||
XFAIL xfail_demo.py::test_hello6
|
||||
reason: reason
|
||||
XFAIL xfail_demo.py::test_hello7
|
||||
|
||||
======================== 7 xfailed in 0.12 seconds =========================
|
||||
|
||||
.. _`skip/xfail with parametrize`:
|
||||
|
||||
4
doc/en/tidelift.rst
Normal file
4
doc/en/tidelift.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
|
||||
.. include:: ../../TIDELIFT.rst
|
||||
@@ -8,7 +8,7 @@ Temporary directories and files
|
||||
The ``tmp_path`` fixture
|
||||
------------------------
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
||||
You can use the ``tmp_path`` fixture which will
|
||||
@@ -43,7 +43,7 @@ Running this would result in a passed test except for the last
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_tmp_path.py F [100%]
|
||||
@@ -66,10 +66,12 @@ Running this would result in a passed test except for the last
|
||||
test_tmp_path.py:13: AssertionError
|
||||
========================= 1 failed in 0.12 seconds =========================
|
||||
|
||||
.. _`tmp_path_factory example`:
|
||||
|
||||
The ``tmp_path_factory`` fixture
|
||||
--------------------------------
|
||||
|
||||
.. versionadded:: 3.9
|
||||
|
||||
|
||||
|
||||
The ``tmp_path_factory`` is a session-scoped fixture which can be used
|
||||
@@ -77,6 +79,8 @@ 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
|
||||
--------------------
|
||||
@@ -106,7 +110,7 @@ Running this would result in a passed test except for the last
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_tmpdir.py F [100%]
|
||||
@@ -132,7 +136,7 @@ Running this would result in a passed test except for the last
|
||||
The 'tmpdir_factory' fixture
|
||||
----------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
The ``tmpdir_factory`` is a session-scoped fixture which can be used
|
||||
to create arbitrary temporary directories from any other fixture or test.
|
||||
@@ -174,7 +178,9 @@ the system temporary directory. The base name will be ``pytest-NUM`` where
|
||||
``NUM`` will be incremented with each test run. Moreover, entries older
|
||||
than 3 temporary directories will be removed.
|
||||
|
||||
You can override the default temporary directory setting like this::
|
||||
You can override the default temporary directory setting like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --basetemp=mydir
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ the ``self.db`` values in the traceback:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 2 items
|
||||
|
||||
test_unittest_db.py FF [100%]
|
||||
|
||||
193
doc/en/usage.rst
193
doc/en/usage.rst
@@ -10,9 +10,11 @@ Usage and Invocations
|
||||
Calling pytest through ``python -m pytest``
|
||||
-----------------------------------------------------
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
You can invoke testing through the Python interpreter from the command line::
|
||||
|
||||
You can invoke testing through the Python interpreter from the command line:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
python -m pytest [...]
|
||||
|
||||
@@ -34,7 +36,7 @@ Running ``pytest`` can result in six different exit codes:
|
||||
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
|
||||
@@ -46,7 +48,9 @@ Getting help on version, option names, environment variables
|
||||
Stopping after the first (or N) failures
|
||||
---------------------------------------------------
|
||||
|
||||
To stop the testing process after the first (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
|
||||
@@ -60,19 +64,19 @@ 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"
|
||||
|
||||
@@ -87,18 +91,22 @@ The example above will run ``TestMyClass.test_something`` but not ``TestMyClass
|
||||
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::
|
||||
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::
|
||||
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
|
||||
|
||||
@@ -108,7 +116,7 @@ For more information see :ref:`marks <mark>`.
|
||||
|
||||
**Run tests from packages**
|
||||
|
||||
::
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pyargs pkg.testing
|
||||
|
||||
@@ -118,7 +126,9 @@ This will import ``pkg.testing`` and use its filesystem location to find and run
|
||||
Modifying Python traceback printing
|
||||
----------------------------------------------
|
||||
|
||||
Examples for modifying traceback printing::
|
||||
Examples for modifying traceback printing:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --showlocals # show local variables in tracebacks
|
||||
pytest -l # show local variables (shortcut)
|
||||
@@ -145,7 +155,7 @@ option you make sure a trace is shown.
|
||||
Detailed summary report
|
||||
-----------------------
|
||||
|
||||
.. versionadded:: 2.9
|
||||
|
||||
|
||||
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.
|
||||
@@ -194,7 +204,7 @@ Example:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 6 items
|
||||
|
||||
test_example.py .FEsxX [100%]
|
||||
@@ -221,11 +231,12 @@ Example:
|
||||
XFAIL test_example.py::test_xfail
|
||||
reason: xfailing this test
|
||||
XPASS test_example.py::test_xpass always xfail
|
||||
ERROR test_example.py::test_error
|
||||
FAILED test_example.py::test_fail
|
||||
1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds
|
||||
ERROR test_example.py::test_error - assert 0
|
||||
FAILED test_example.py::test_fail - assert 0
|
||||
= 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds =
|
||||
|
||||
The ``-r`` options accepts a number of characters after it, with ``a`` used above meaning "all except passes".
|
||||
The ``-r`` options accepts a number of characters after it, with ``a`` used
|
||||
above meaning "all except passes".
|
||||
|
||||
Here is the full list of available characters that can be used:
|
||||
|
||||
@@ -237,6 +248,7 @@ Here is the full list of available characters that can be used:
|
||||
- ``p`` - passed
|
||||
- ``P`` - passed with output
|
||||
- ``a`` - all except ``pP``
|
||||
- ``A`` - all
|
||||
|
||||
More than one character can be used, so for example to only see failed and skipped tests, you can execute:
|
||||
|
||||
@@ -246,7 +258,7 @@ More than one character can be used, so for example to only see failed and skipp
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 6 items
|
||||
|
||||
test_example.py .FEsxX [100%]
|
||||
@@ -269,9 +281,9 @@ More than one character can be used, so for example to only see failed and skipp
|
||||
|
||||
test_example.py:14: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
FAILED test_example.py::test_fail
|
||||
FAILED test_example.py::test_fail - assert 0
|
||||
SKIPPED [1] $REGENDOC_TMPDIR/test_example.py:23: skipping this test
|
||||
1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds
|
||||
= 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds =
|
||||
|
||||
Using ``p`` lists the passing tests, whilst ``P`` adds an extra section "PASSES" with those tests that passed but had
|
||||
captured output:
|
||||
@@ -282,7 +294,7 @@ captured output:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 6 items
|
||||
|
||||
test_example.py .FEsxX [100%]
|
||||
@@ -304,13 +316,13 @@ captured output:
|
||||
E assert 0
|
||||
|
||||
test_example.py:14: AssertionError
|
||||
========================= short test summary info ==========================
|
||||
PASSED test_example.py::test_ok
|
||||
================================== PASSES ==================================
|
||||
_________________________________ test_ok __________________________________
|
||||
--------------------------- Captured stdout call ---------------------------
|
||||
ok
|
||||
1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds
|
||||
========================= short test summary info ==========================
|
||||
PASSED test_example.py::test_ok
|
||||
= 1 failed, 1 passed, 1 skipped, 1 xfailed, 1 xpassed, 1 error in 0.12 seconds =
|
||||
|
||||
.. _pdb-option:
|
||||
|
||||
@@ -320,13 +332,17 @@ Dropping to PDB_ (Python Debugger) on failures
|
||||
.. _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::
|
||||
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::
|
||||
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
|
||||
@@ -349,7 +365,9 @@ Dropping to PDB_ (Python Debugger) 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::
|
||||
``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
|
||||
|
||||
@@ -368,10 +386,8 @@ 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.
|
||||
* Any later output produced within the same test will not be captured and will
|
||||
instead get sent directly to ``sys.stdout``. Note that this holds true even
|
||||
for test output occurring after you exit the interactive PDB_ tracing session
|
||||
and continue with the regular test run.
|
||||
* Output capture gets resumed when ending the debugger session (via the
|
||||
``continue`` command).
|
||||
|
||||
|
||||
.. _`breakpoint-builtin`:
|
||||
@@ -394,7 +410,9 @@ Profiling test execution duration
|
||||
|
||||
.. versionadded: 2.2
|
||||
|
||||
To get a list of the slowest 10 test durations::
|
||||
To get a list of the slowest 10 test durations:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --durations=10
|
||||
|
||||
@@ -404,13 +422,15 @@ Creating JUnitXML format files
|
||||
----------------------------------------------------
|
||||
|
||||
To create result files which can be read by Jenkins_ or other Continuous
|
||||
integration servers, use this invocation::
|
||||
integration servers, use this invocation:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --junitxml=path
|
||||
|
||||
to create an XML file at ``path``.
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
To set the name of the root test suite xml item, you can configure the ``junit_suite_name`` option in your config file:
|
||||
|
||||
@@ -438,13 +458,6 @@ instead, configure the ``junit_duration_report`` option like this:
|
||||
record_property
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 2.8
|
||||
.. versionchanged:: 3.5
|
||||
|
||||
Fixture renamed from ``record_xml_property`` to ``record_property`` as user
|
||||
properties are now available to all reporters.
|
||||
``record_xml_property`` is now deprecated.
|
||||
|
||||
If you want to log additional information for a test, you can use the
|
||||
``record_property`` fixture:
|
||||
|
||||
@@ -502,15 +515,13 @@ Will result in:
|
||||
|
||||
.. warning::
|
||||
|
||||
``record_property`` is an experimental feature and may change in the future.
|
||||
|
||||
Also please note that using this feature will break any schema verification.
|
||||
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
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 3.4
|
||||
|
||||
|
||||
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:
|
||||
@@ -567,43 +578,45 @@ Instead, this will add an attribute ``assertions="REQ-1234"`` inside the generat
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
LogXML: add_global_property
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
.. warning::
|
||||
|
||||
.. versionadded:: 3.0
|
||||
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.
|
||||
|
||||
If you want to add a properties node in the testsuite level, which may contains properties that are relevant
|
||||
to all testcases you can use ``LogXML.add_global_properties``
|
||||
.. _record_testsuite_property example:
|
||||
|
||||
record_testsuite_property
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 4.5
|
||||
|
||||
If you want to add a properties node at the test-suite level, which may contains properties
|
||||
that are relevant to all tests, you can use the ``record_testsuite_property`` session-scoped fixture:
|
||||
|
||||
The ``record_testsuite_property`` session-scoped fixture can be used to add properties relevant
|
||||
to all tests.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def log_global_env_facts(f):
|
||||
|
||||
if pytest.config.pluginmanager.hasplugin("junitxml"):
|
||||
my_junit = getattr(pytest.config, "_xml", None)
|
||||
|
||||
my_junit.add_global_property("ARCH", "PPC")
|
||||
my_junit.add_global_property("STORAGE_TYPE", "CEPH")
|
||||
|
||||
|
||||
@pytest.mark.usefixtures(log_global_env_facts.__name__)
|
||||
def start_and_prepare_env():
|
||||
pass
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def log_global_env_facts(record_testsuite_property):
|
||||
record_testsuite_property("ARCH", "PPC")
|
||||
record_testsuite_property("STORAGE_TYPE", "CEPH")
|
||||
|
||||
|
||||
class TestMe(object):
|
||||
def test_foo(self):
|
||||
assert True
|
||||
|
||||
This will add a property node below the testsuite node to the generated xml:
|
||||
The fixture is a callable which receives ``name`` and ``value`` of a ``<property>`` tag
|
||||
added at the test-suite level of the generated xml:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.006">
|
||||
<testsuite errors="0" failures="0" name="pytest" skipped="0" tests="1" time="0.006">
|
||||
<properties>
|
||||
<property name="ARCH" value="PPC"/>
|
||||
<property name="STORAGE_TYPE" value="CEPH"/>
|
||||
@@ -611,23 +624,25 @@ This will add a property node below the testsuite node to the generated xml:
|
||||
<testcase classname="test_me.TestMe" file="test_me.py" line="16" name="test_foo" time="0.000243663787842"/>
|
||||
</testsuite>
|
||||
|
||||
.. warning::
|
||||
``name`` must be a string, ``value`` will be converted to a string and properly xml-escaped.
|
||||
|
||||
The generated XML is compatible with the latest ``xunit`` standard, contrary to `record_property`_
|
||||
and `record_xml_attribute`_.
|
||||
|
||||
This is an experimental feature, and its interface might be replaced
|
||||
by something more powerful and general in future versions. The
|
||||
functionality per-se will be kept.
|
||||
|
||||
Creating resultlog format files
|
||||
----------------------------------------------------
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
|
||||
This option is rarely used and is scheduled for removal in 5.0.
|
||||
|
||||
See `the deprecation docs <https://docs.pytest.org/en/latest/deprecations.html#result-log-result-log>`__
|
||||
for more information.
|
||||
|
||||
To create plain-text machine-readable result files you can issue::
|
||||
To create plain-text machine-readable result files you can issue:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --resultlog=path
|
||||
|
||||
@@ -640,7 +655,9 @@ by the `PyPy-test`_ web page to show test results over several revisions.
|
||||
Sending test report to online pastebin service
|
||||
-----------------------------------------------------
|
||||
|
||||
**Creating a URL for each test failure**::
|
||||
**Creating a URL for each test failure**:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pastebin=failed
|
||||
|
||||
@@ -648,12 +665,30 @@ This will submit test run information to a remote Paste service and
|
||||
provide a URL for each failure. You may select tests as usual or add
|
||||
for example ``-x`` if you only want to send one particular failure.
|
||||
|
||||
**Creating a URL for a whole test session log**::
|
||||
**Creating a URL for a whole test session log**:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest --pastebin=all
|
||||
|
||||
Currently only pasting to the http://bpaste.net service is implemented.
|
||||
|
||||
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
|
||||
-----------------
|
||||
|
||||
@@ -661,7 +696,9 @@ 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::
|
||||
executing doctest tests from text files, invoke pytest like this:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
pytest -p no:doctest
|
||||
|
||||
@@ -670,7 +707,7 @@ executing doctest tests from text files, invoke pytest like this::
|
||||
Calling pytest from Python code
|
||||
----------------------------------------------------
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
|
||||
You can invoke ``pytest`` from Python code directly::
|
||||
|
||||
@@ -693,7 +730,9 @@ You can specify additional plugins to ``pytest.main``::
|
||||
pytest.main(["-qq"], plugins=[MyPlugin()])
|
||||
|
||||
Running it will show that ``MyPlugin`` was added and its
|
||||
hook was invoked::
|
||||
hook was invoked:
|
||||
|
||||
.. code-block:: pytest
|
||||
|
||||
$ python myinvoke.py
|
||||
.FEsxX. [100%]*** test run reporting finishing
|
||||
|
||||
@@ -3,18 +3,22 @@
|
||||
Warnings Capture
|
||||
================
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
|
||||
Starting from version ``3.1``, pytest now automatically catches warnings during test execution
|
||||
and displays them at the end of the session::
|
||||
and displays them at the end of the session:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# content of test_show_warnings.py
|
||||
import warnings
|
||||
|
||||
|
||||
def api_v1():
|
||||
warnings.warn(UserWarning("api v1, should use functions from v2"))
|
||||
return 1
|
||||
|
||||
|
||||
def test_one():
|
||||
assert api_v1() == 1
|
||||
|
||||
@@ -26,14 +30,14 @@ Running pytest now produces this output:
|
||||
=========================== test session starts ============================
|
||||
platform linux -- Python 3.x.y, pytest-4.x.y, py-1.x.y, pluggy-0.x.y
|
||||
cachedir: $PYTHON_PREFIX/.pytest_cache
|
||||
rootdir: $REGENDOC_TMPDIR, inifile:
|
||||
rootdir: $REGENDOC_TMPDIR
|
||||
collected 1 item
|
||||
|
||||
test_show_warnings.py . [100%]
|
||||
|
||||
============================= warnings summary =============================
|
||||
test_show_warnings.py::test_one
|
||||
$REGENDOC_TMPDIR/test_show_warnings.py:4: UserWarning: api v1, should use functions from v2
|
||||
$REGENDOC_TMPDIR/test_show_warnings.py:5: UserWarning: api v1, should use functions from v2
|
||||
warnings.warn(UserWarning("api v1, should use functions from v2"))
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
@@ -52,14 +56,14 @@ them into errors:
|
||||
def test_one():
|
||||
> assert api_v1() == 1
|
||||
|
||||
test_show_warnings.py:8:
|
||||
test_show_warnings.py:10:
|
||||
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||
|
||||
def api_v1():
|
||||
> warnings.warn(UserWarning("api v1, should use functions from v2"))
|
||||
E UserWarning: api v1, should use functions from v2
|
||||
|
||||
test_show_warnings.py:4: UserWarning
|
||||
test_show_warnings.py:5: UserWarning
|
||||
1 failed in 0.12 seconds
|
||||
|
||||
The same option can be set in the ``pytest.ini`` file using the ``filterwarnings`` ini option.
|
||||
@@ -86,7 +90,7 @@ documentation for other examples and advanced usage.
|
||||
``@pytest.mark.filterwarnings``
|
||||
-------------------------------
|
||||
|
||||
.. versionadded:: 3.2
|
||||
|
||||
|
||||
You can use the ``@pytest.mark.filterwarnings`` to add warning filters to specific test items,
|
||||
allowing you to have finer control of which warnings should be captured at test, class or
|
||||
@@ -152,8 +156,8 @@ using an external system.
|
||||
DeprecationWarning and PendingDeprecationWarning
|
||||
------------------------------------------------
|
||||
|
||||
.. versionadded:: 3.8
|
||||
.. versionchanged:: 3.9
|
||||
|
||||
|
||||
|
||||
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>`_.
|
||||
@@ -195,28 +199,36 @@ Ensuring code triggers a deprecation warning
|
||||
|
||||
You can also call a global helper for checking
|
||||
that a certain function call triggers a ``DeprecationWarning`` or
|
||||
``PendingDeprecationWarning``::
|
||||
``PendingDeprecationWarning``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
def test_global():
|
||||
pytest.deprecated_call(myfunction, 17)
|
||||
|
||||
By default, ``DeprecationWarning`` and ``PendingDeprecationWarning`` will not be
|
||||
caught when using ``pytest.warns`` or ``recwarn`` because default Python warnings filters hide
|
||||
them. If you wish to record them in your own code, use the
|
||||
command ``warnings.simplefilter('always')``::
|
||||
command ``warnings.simplefilter('always')``:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
|
||||
def test_deprecation(recwarn):
|
||||
warnings.simplefilter('always')
|
||||
warnings.simplefilter("always")
|
||||
warnings.warn("deprecated", DeprecationWarning)
|
||||
assert len(recwarn) == 1
|
||||
assert recwarn.pop(DeprecationWarning)
|
||||
|
||||
You can also use it as a contextmanager::
|
||||
You can also use it as a contextmanager:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def test_global():
|
||||
with pytest.deprecated_call():
|
||||
@@ -235,14 +247,17 @@ You can also use it as a contextmanager::
|
||||
Asserting warnings with the warns function
|
||||
------------------------------------------
|
||||
|
||||
.. versionadded:: 2.8
|
||||
|
||||
|
||||
You can check that code raises a particular warning using ``pytest.warns``,
|
||||
which works in a similar manner to :ref:`raises <assertraises>`::
|
||||
which works in a similar manner to :ref:`raises <assertraises>`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import warnings
|
||||
import pytest
|
||||
|
||||
|
||||
def test_warning():
|
||||
with pytest.warns(UserWarning):
|
||||
warnings.warn("my warning", UserWarning)
|
||||
@@ -269,7 +284,9 @@ You can also call ``pytest.warns`` on a function or code string::
|
||||
|
||||
The function also returns a list of all raised warnings (as
|
||||
``warnings.WarningMessage`` objects), which you can query for
|
||||
additional information::
|
||||
additional information:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with pytest.warns(RuntimeWarning) as record:
|
||||
warnings.warn("another warning", RuntimeWarning)
|
||||
@@ -297,7 +314,9 @@ You can record raised warnings either using ``pytest.warns`` or with
|
||||
the ``recwarn`` fixture.
|
||||
|
||||
To record with ``pytest.warns`` without asserting anything about the warnings,
|
||||
pass ``None`` as the expected warning type::
|
||||
pass ``None`` as the expected warning type:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
with pytest.warns(None) as record:
|
||||
warnings.warn("user", UserWarning)
|
||||
@@ -307,10 +326,13 @@ pass ``None`` as the expected warning type::
|
||||
assert str(record[0].message) == "user"
|
||||
assert str(record[1].message) == "runtime"
|
||||
|
||||
The ``recwarn`` fixture will record warnings for the whole function::
|
||||
The ``recwarn`` fixture will record warnings for the whole function:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import warnings
|
||||
|
||||
|
||||
def test_hello(recwarn):
|
||||
warnings.warn("hello", UserWarning)
|
||||
assert len(recwarn) == 1
|
||||
@@ -355,7 +377,7 @@ custom error message.
|
||||
Internal pytest warnings
|
||||
------------------------
|
||||
|
||||
.. versionadded:: 3.8
|
||||
|
||||
|
||||
pytest may generate its own warnings in some situations, such as improper usage or deprecated features.
|
||||
|
||||
@@ -378,7 +400,7 @@ defines an ``__init__`` constructor, as this prevents the class from being insta
|
||||
|
||||
============================= warnings summary =============================
|
||||
test_pytest_warnings.py:1
|
||||
$REGENDOC_TMPDIR/test_pytest_warnings.py:1: PytestWarning: cannot collect test class 'Test' because it has a __init__ constructor
|
||||
$REGENDOC_TMPDIR/test_pytest_warnings.py:1: PytestCollectionWarning: cannot collect test class 'Test' because it has a __init__ constructor (from: test_pytest_warnings.py)
|
||||
class Test:
|
||||
|
||||
-- Docs: https://docs.pytest.org/en/latest/warnings.html
|
||||
@@ -393,8 +415,20 @@ The following warning types ares used by pytest and are part of the public API:
|
||||
|
||||
.. autoclass:: pytest.PytestWarning
|
||||
|
||||
.. autoclass:: pytest.PytestAssertRewriteWarning
|
||||
|
||||
.. autoclass:: pytest.PytestCacheWarning
|
||||
|
||||
.. autoclass:: pytest.PytestCollectionWarning
|
||||
|
||||
.. autoclass:: pytest.PytestConfigWarning
|
||||
|
||||
.. autoclass:: pytest.PytestDeprecationWarning
|
||||
|
||||
.. autoclass:: pytest.RemovedInPytest4Warning
|
||||
|
||||
.. autoclass:: pytest.PytestExperimentalApiWarning
|
||||
|
||||
.. autoclass:: pytest.PytestUnhandledCoroutineWarning
|
||||
|
||||
.. autoclass:: pytest.PytestUnknownMarkWarning
|
||||
|
||||
.. autoclass:: pytest.RemovedInPytest4Warning
|
||||
|
||||
@@ -223,7 +223,6 @@ import ``helper.py`` normally. The contents of
|
||||
pytest.register_assert_rewrite("pytest_foo.helper")
|
||||
|
||||
|
||||
|
||||
Requiring/Loading plugins in a test module or conftest file
|
||||
-----------------------------------------------------------
|
||||
|
||||
@@ -286,6 +285,26 @@ the plugin manager like this:
|
||||
If you want to look at the names of existing plugins, use
|
||||
the ``--trace-config`` option.
|
||||
|
||||
|
||||
.. _registering-markers:
|
||||
|
||||
Registering custom markers
|
||||
--------------------------
|
||||
|
||||
If your plugin uses any markers, you should register them so that they appear in
|
||||
pytest's help text and do not :ref:`cause spurious warnings <unknown-marks>`.
|
||||
For example, the following plugin would register ``cool_marker`` and
|
||||
``mark_with`` for all users:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def pytest_configure(config):
|
||||
config.addinivalue_line("markers", "cool_marker: this one is for cool tests.")
|
||||
config.addinivalue_line(
|
||||
"markers", "mark_with(arg, arg2): this marker takes arguments."
|
||||
)
|
||||
|
||||
|
||||
Testing plugins
|
||||
---------------
|
||||
|
||||
@@ -496,7 +515,7 @@ hookwrapper: executing around other hooks
|
||||
|
||||
.. currentmodule:: _pytest.core
|
||||
|
||||
.. versionadded:: 2.7
|
||||
|
||||
|
||||
pytest plugins can implement hook wrappers which wrap the execution
|
||||
of other hook implementations. A hook wrapper is a generator function
|
||||
@@ -509,10 +528,13 @@ a :py:class:`Result <pluggy._Result>` instance which encapsulates a result or
|
||||
exception info. The yield point itself will thus typically not raise
|
||||
exceptions (unless there are bugs).
|
||||
|
||||
Here is an example definition of a hook wrapper::
|
||||
Here is an example definition of a hook wrapper:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import pytest
|
||||
|
||||
|
||||
@pytest.hookimpl(hookwrapper=True)
|
||||
def pytest_pyfunc_call(pyfuncitem):
|
||||
do_something_before_next_hook_executes()
|
||||
@@ -617,10 +639,13 @@ if you depend on a plugin that is not installed, validation will fail and
|
||||
the error message will not make much sense to your users.
|
||||
|
||||
One approach is to defer the hook implementation to a new plugin instead of
|
||||
declaring the hook functions directly in your plugin module, for example::
|
||||
declaring the hook functions directly in your plugin module, for example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
# contents of myplugin.py
|
||||
|
||||
|
||||
class DeferPlugin(object):
|
||||
"""Simple plugin to defer pytest-xdist hook functions."""
|
||||
|
||||
@@ -628,8 +653,9 @@ declaring the hook functions directly in your plugin module, for example::
|
||||
"""standard xdist hook function.
|
||||
"""
|
||||
|
||||
|
||||
def pytest_configure(config):
|
||||
if config.pluginmanager.hasplugin('xdist'):
|
||||
if config.pluginmanager.hasplugin("xdist"):
|
||||
config.pluginmanager.register(DeferPlugin())
|
||||
|
||||
This has the added benefit of allowing you to conditionally install hooks
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"yield_fixture" functions
|
||||
---------------------------------------------------------------
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
.. versionadded:: 2.4
|
||||
|
||||
|
||||
|
||||
.. important::
|
||||
Since pytest-3.0, fixtures using the normal ``fixture`` decorator can use a ``yield``
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import json
|
||||
|
||||
import py
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import sys
|
||||
from distutils.core import setup
|
||||
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
REM install pypy using choco
|
||||
REM redirect to a file because choco install python.pypy is too noisy. If the command fails, write output to console
|
||||
choco install python.pypy > pypy-inst.log 2>&1 || (type pypy-inst.log & exit /b 1)
|
||||
set PATH=C:\tools\pypy\pypy;%PATH% # so tox can find pypy
|
||||
echo PyPy installed
|
||||
pypy --version
|
||||
@@ -1,10 +0,0 @@
|
||||
REM scripts called by AppVeyor to setup the environment variables to enable coverage
|
||||
if not defined PYTEST_NO_COVERAGE (
|
||||
set "COVERAGE_FILE=%CD%\.coverage"
|
||||
set "COVERAGE_PROCESS_START=%CD%\.coveragerc"
|
||||
set "_PYTEST_TOX_COVERAGE_RUN=coverage run -m"
|
||||
set "_PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess"
|
||||
echo Coverage setup completed
|
||||
) else (
|
||||
echo Skipping coverage setup, PYTEST_NO_COVERAGE is set
|
||||
)
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Invoke development tasks.
|
||||
"""
|
||||
|
||||
7
scripts/setup-coverage-vars.bat
Normal file
7
scripts/setup-coverage-vars.bat
Normal file
@@ -0,0 +1,7 @@
|
||||
if "%PYTEST_COVERAGE%" == "1" (
|
||||
set "_PYTEST_TOX_COVERAGE_RUN=coverage run -m"
|
||||
set "_PYTEST_TOX_EXTRA_DEP=coverage-enable-subprocess"
|
||||
echo Coverage vars configured, PYTEST_COVERAGE=%PYTEST_COVERAGE%
|
||||
) else (
|
||||
echo Skipping coverage vars setup, PYTEST_COVERAGE=%PYTEST_COVERAGE%
|
||||
)
|
||||
@@ -1,11 +1,16 @@
|
||||
REM script called by AppVeyor to combine and upload coverage information to codecov
|
||||
if not defined PYTEST_NO_COVERAGE (
|
||||
REM script called by Azure to combine and upload coverage information to codecov
|
||||
if "%PYTEST_COVERAGE%" == "1" (
|
||||
echo Prepare to upload coverage information
|
||||
C:\Python36\Scripts\pip install codecov
|
||||
C:\Python36\Scripts\coverage combine
|
||||
C:\Python36\Scripts\coverage xml --ignore-errors
|
||||
C:\Python36\Scripts\coverage report -m --ignore-errors
|
||||
scripts\appveyor-retry C:\Python36\Scripts\codecov --required -X gcov pycov search -f coverage.xml --flags %TOXENV:-= % windows
|
||||
if defined CODECOV_TOKEN (
|
||||
echo CODECOV_TOKEN defined
|
||||
) else (
|
||||
echo CODECOV_TOKEN NOT defined
|
||||
)
|
||||
python -m pip install codecov
|
||||
python -m coverage combine
|
||||
python -m coverage xml
|
||||
python -m coverage report -m
|
||||
scripts\retry python -m codecov --required -X gcov pycov search -f coverage.xml --name %PYTEST_CODECOV_NAME%
|
||||
) else (
|
||||
echo Skipping coverage upload, PYTEST_NO_COVERAGE is set
|
||||
echo Skipping coverage upload, PYTEST_COVERAGE=%PYTEST_COVERAGE%
|
||||
)
|
||||
|
||||
18
setup.py
18
setup.py
@@ -1,30 +1,25 @@
|
||||
import os
|
||||
|
||||
# -*- coding: utf-8 -*-
|
||||
from setuptools import setup
|
||||
|
||||
|
||||
# TODO: if py gets upgrade to >=1.6,
|
||||
# remove _width_of_current_line in terminal.py
|
||||
INSTALL_REQUIRES = [
|
||||
"py>=1.5.0",
|
||||
"six>=1.10.0",
|
||||
"setuptools",
|
||||
"packaging",
|
||||
"attrs>=17.4.0",
|
||||
'more-itertools>=4.0.0,<6.0.0;python_version<="2.7"',
|
||||
'more-itertools>=4.0.0;python_version>"2.7"',
|
||||
"atomicwrites>=1.0",
|
||||
'funcsigs;python_version<"3.0"',
|
||||
'funcsigs>=1.0;python_version<"3.0"',
|
||||
'pathlib2>=2.2.0;python_version<"3.6"',
|
||||
'colorama;sys_platform=="win32"',
|
||||
"pluggy>=0.12,<1.0",
|
||||
"importlib-metadata>=0.12",
|
||||
"wcwidth",
|
||||
]
|
||||
|
||||
|
||||
# if _PYTEST_SETUP_SKIP_PLUGGY_DEP is set, skip installing pluggy;
|
||||
# used by tox.ini to test with pluggy master
|
||||
if "_PYTEST_SETUP_SKIP_PLUGGY_DEP" not in os.environ:
|
||||
INSTALL_REQUIRES.append("pluggy>=0.7")
|
||||
|
||||
|
||||
def main():
|
||||
setup(
|
||||
use_scm_version={"write_to": "src/_pytest/_version.py"},
|
||||
@@ -33,6 +28,7 @@ def main():
|
||||
# fmt: off
|
||||
extras_require={
|
||||
"testing": [
|
||||
"argcomplete",
|
||||
"hypothesis>=3.56",
|
||||
"nose",
|
||||
"requests",
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
__all__ = ["__version__"]
|
||||
|
||||
try:
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""allow bash-completion for argparse with argcomplete if installed
|
||||
needs argcomplete>=0.5.6 for python 3.2/3.3 (older versions fail
|
||||
to find the magic string, so _ARGCOMPLETE env. var is never set, and
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""" python inspection/code generation API """
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# copied from python-2.7.3's traceback.py
|
||||
# CHANGES:
|
||||
# - some_str is replaced, trying to create unicode strings
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user