@@ -2073,6 +2073,21 @@ def test_foobar(i): pass
2073
2073
""" ,
2074
2074
)
2075
2075
2076
+ @pytest .fixture
2077
+ def more_tests_files (self , pytester : Pytester ) -> None :
2078
+ pytester .makepyfile (
2079
+ test_bar = """
2080
+ import pytest
2081
+ @pytest.mark.parametrize('i', range(30))
2082
+ def test_bar(i): pass
2083
+ """ ,
2084
+ test_foo = """
2085
+ import pytest
2086
+ @pytest.mark.parametrize('i', range(5))
2087
+ def test_foo(i): pass
2088
+ """ ,
2089
+ )
2090
+
2076
2091
def test_zero_tests_collected (self , pytester : Pytester ) -> None :
2077
2092
"""Some plugins (testmon for example) might issue pytest_runtest_logreport without any tests being
2078
2093
actually collected (#2971)."""
@@ -2169,6 +2184,52 @@ def test_count(self, many_tests_files, pytester: Pytester) -> None:
2169
2184
]
2170
2185
)
2171
2186
2187
+ def test_times (self , many_tests_files , pytester : Pytester ) -> None :
2188
+ pytester .makeini (
2189
+ """
2190
+ [pytest]
2191
+ console_output_style = times
2192
+ """
2193
+ )
2194
+ output = pytester .runpytest ()
2195
+ output .stdout .re_match_lines (
2196
+ [
2197
+ r"test_bar.py \.{10} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2198
+ r"test_foo.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2199
+ r"test_foobar.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2200
+ ]
2201
+ )
2202
+
2203
+ def test_times_multiline (
2204
+ self , more_tests_files , monkeypatch , pytester : Pytester
2205
+ ) -> None :
2206
+ monkeypatch .setenv ("COLUMNS" , "40" )
2207
+ pytester .makeini (
2208
+ """
2209
+ [pytest]
2210
+ console_output_style = times
2211
+ """
2212
+ )
2213
+ output = pytester .runpytest ()
2214
+ output .stdout .re_match_lines (
2215
+ [
2216
+ r"test_bar.py ..................." ,
2217
+ r"........... \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2218
+ r"test_foo.py \.{5} \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2219
+ ],
2220
+ consecutive = True ,
2221
+ )
2222
+
2223
+ def test_times_none_collected (self , pytester : Pytester ) -> None :
2224
+ pytester .makeini (
2225
+ """
2226
+ [pytest]
2227
+ console_output_style = times
2228
+ """
2229
+ )
2230
+ output = pytester .runpytest ()
2231
+ assert output .ret == ExitCode .NO_TESTS_COLLECTED
2232
+
2172
2233
def test_verbose (self , many_tests_files , pytester : Pytester ) -> None :
2173
2234
output = pytester .runpytest ("-v" )
2174
2235
output .stdout .re_match_lines (
@@ -2195,6 +2256,22 @@ def test_verbose_count(self, many_tests_files, pytester: Pytester) -> None:
2195
2256
]
2196
2257
)
2197
2258
2259
+ def test_verbose_times (self , many_tests_files , pytester : Pytester ) -> None :
2260
+ pytester .makeini (
2261
+ """
2262
+ [pytest]
2263
+ console_output_style = times
2264
+ """
2265
+ )
2266
+ output = pytester .runpytest ("-v" )
2267
+ output .stdout .re_match_lines (
2268
+ [
2269
+ r"test_bar.py::test_bar\[0\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2270
+ r"test_foo.py::test_foo\[4\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2271
+ r"test_foobar.py::test_foobar\[4\] PASSED \s+ \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2}$" ,
2272
+ ]
2273
+ )
2274
+
2198
2275
def test_xdist_normal (
2199
2276
self , many_tests_files , pytester : Pytester , monkeypatch
2200
2277
) -> None :
@@ -2247,6 +2324,26 @@ def test_xdist_verbose(
2247
2324
]
2248
2325
)
2249
2326
2327
+ def test_xdist_times (
2328
+ self , many_tests_files , pytester : Pytester , monkeypatch
2329
+ ) -> None :
2330
+ pytest .importorskip ("xdist" )
2331
+ monkeypatch .delenv ("PYTEST_DISABLE_PLUGIN_AUTOLOAD" , raising = False )
2332
+ pytester .makeini (
2333
+ """
2334
+ [pytest]
2335
+ console_output_style = times
2336
+ """
2337
+ )
2338
+ output = pytester .runpytest ("-n2" , "-v" )
2339
+ output .stdout .re_match_lines_random (
2340
+ [
2341
+ r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_bar.py::test_bar\[1\]" ,
2342
+ r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_foo.py::test_foo\[1\]" ,
2343
+ r"\[gw\d\] \d{1,3}[\.[a-z\ ]{1,2}\d{0,3}\w{1,2} PASSED test_foobar.py::test_foobar\[1\]" ,
2344
+ ]
2345
+ )
2346
+
2250
2347
def test_capture_no (self , many_tests_files , pytester : Pytester ) -> None :
2251
2348
output = pytester .runpytest ("-s" )
2252
2349
output .stdout .re_match_lines (
@@ -2537,6 +2634,27 @@ def test_format_session_duration(seconds, expected):
2537
2634
assert format_session_duration (seconds ) == expected
2538
2635
2539
2636
2637
+ @pytest .mark .parametrize (
2638
+ "seconds, expected" ,
2639
+ [
2640
+ (3600 * 100 - 60 , " 99h 59m" ),
2641
+ (31 * 60 - 1 , " 30m 59s" ),
2642
+ (10.1236 , " 10.124s" ),
2643
+ (9.1236 , " 9.124s" ),
2644
+ (0.1236 , " 123.6ms" ),
2645
+ (0.01236 , " 12.36ms" ),
2646
+ (0.001236 , " 1.236ms" ),
2647
+ (0.0001236 , " 123.6us" ),
2648
+ (0.00001236 , " 12.36us" ),
2649
+ (0.000001236 , " 1.236us" ),
2650
+ ],
2651
+ )
2652
+ def test_format_node_duration (seconds : float , expected : str ) -> None :
2653
+ from _pytest .terminal import format_node_duration
2654
+
2655
+ assert format_node_duration (seconds ) == expected
2656
+
2657
+
2540
2658
def test_collecterror (pytester : Pytester ) -> None :
2541
2659
p1 = pytester .makepyfile ("raise SyntaxError()" )
2542
2660
result = pytester .runpytest ("-ra" , str (p1 ))
0 commit comments