@@ -2073,6 +2073,21 @@ def test_foobar(i): pass
20732073 """ ,
20742074 )
20752075
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+
20762091 def test_zero_tests_collected (self , pytester : Pytester ) -> None :
20772092 """Some plugins (testmon for example) might issue pytest_runtest_logreport without any tests being
20782093 actually collected (#2971)."""
@@ -2169,6 +2184,52 @@ def test_count(self, many_tests_files, pytester: Pytester) -> None:
21692184 ]
21702185 )
21712186
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+
21722233 def test_verbose (self , many_tests_files , pytester : Pytester ) -> None :
21732234 output = pytester .runpytest ("-v" )
21742235 output .stdout .re_match_lines (
@@ -2195,6 +2256,22 @@ def test_verbose_count(self, many_tests_files, pytester: Pytester) -> None:
21952256 ]
21962257 )
21972258
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+
21982275 def test_xdist_normal (
21992276 self , many_tests_files , pytester : Pytester , monkeypatch
22002277 ) -> None :
@@ -2247,6 +2324,26 @@ def test_xdist_verbose(
22472324 ]
22482325 )
22492326
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+
22502347 def test_capture_no (self , many_tests_files , pytester : Pytester ) -> None :
22512348 output = pytester .runpytest ("-s" )
22522349 output .stdout .re_match_lines (
@@ -2537,6 +2634,27 @@ def test_format_session_duration(seconds, expected):
25372634 assert format_session_duration (seconds ) == expected
25382635
25392636
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+
25402658def test_collecterror (pytester : Pytester ) -> None :
25412659 p1 = pytester .makepyfile ("raise SyntaxError()" )
25422660 result = pytester .runpytest ("-ra" , str (p1 ))
0 commit comments