diff --git a/.riot/requirements/10b8fc3.txt b/.riot/requirements/10b8fc3.txt index 9324ae55f3a..53b796d5c8d 100644 --- a/.riot/requirements/10b8fc3.txt +++ b/.riot/requirements/10b8fc3.txt @@ -2,30 +2,31 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --no-annotate .riot/requirements/10b8fc3.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/10b8fc3.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py==1.11.0 pytest==6.2.5 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 toml==0.10.2 +typing-extensions==4.13.1 diff --git a/.riot/requirements/1163993.txt b/.riot/requirements/1163993.txt index 6ecfee3c50b..30811bff194 100644 --- a/.riot/requirements/1163993.txt +++ b/.riot/requirements/1163993.txt @@ -2,30 +2,31 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --no-annotate .riot/requirements/1163993.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1163993.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py==1.11.0 pytest==6.2.5 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 toml==0.10.2 +typing-extensions==4.13.1 diff --git a/.riot/requirements/1252d0f.txt b/.riot/requirements/1252d0f.txt index 53b83cf7b70..a9a6b899082 100644 --- a/.riot/requirements/1252d0f.txt +++ b/.riot/requirements/1252d0f.txt @@ -2,28 +2,29 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --no-annotate .riot/requirements/1252d0f.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1252d0f.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 -pytest==8.1.1 -pytest-cov==5.0.0 +packaging==24.2 +pluggy==1.5.0 +pytest==8.3.5 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 +typing-extensions==4.13.1 diff --git a/.riot/requirements/144615f.txt b/.riot/requirements/144615f.txt index ab3ffaf7ef7..851073b2b61 100644 --- a/.riot/requirements/144615f.txt +++ b/.riot/requirements/144615f.txt @@ -2,31 +2,31 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --no-annotate --resolver=backtracking .riot/requirements/144615f.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/144615f.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 -pytest==8.1.1 -pytest-cov==5.0.0 +packaging==24.2 +pluggy==1.5.0 +pytest==8.3.5 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 +tomli==2.2.1 +typing-extensions==4.13.1 diff --git a/.riot/requirements/14ca37f.txt b/.riot/requirements/14ca37f.txt index 0d9ec3e2183..466aa733506 100644 --- a/.riot/requirements/14ca37f.txt +++ b/.riot/requirements/14ca37f.txt @@ -2,33 +2,33 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --no-annotate --resolver=backtracking .riot/requirements/14ca37f.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/14ca37f.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py==1.11.0 pytest==6.2.5 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 toml==0.10.2 -tomli==2.0.1 -typing-extensions==4.11.0 +tomli==2.2.1 +typing-extensions==4.13.1 diff --git a/.riot/requirements/166af91.txt b/.riot/requirements/166af91.txt index 3ea3c4ab9b6..f4222458a4c 100644 --- a/.riot/requirements/166af91.txt +++ b/.riot/requirements/166af91.txt @@ -2,23 +2,23 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --no-annotate .riot/requirements/166af91.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/166af91.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 hypothesis==6.45.0 -iniconfig==2.0.0 -mock==5.1.0 -msgpack==1.0.7 +iniconfig==2.1.0 +mock==5.2.0 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py-cpuinfo==9.0.0 -pytest==8.0.0 +pytest==8.3.5 pytest-benchmark==4.0.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-randomly==3.15.0 +pytest-cov==6.1.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 sortedcontainers==2.4.0 -tomli==2.0.1 +tomli==2.2.1 diff --git a/.riot/requirements/17cf97e.txt b/.riot/requirements/17cf97e.txt index cec3b324723..8c5d0c35300 100644 --- a/.riot/requirements/17cf97e.txt +++ b/.riot/requirements/17cf97e.txt @@ -2,28 +2,29 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --no-annotate .riot/requirements/17cf97e.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/17cf97e.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 pytest==7.4.4 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 +typing-extensions==4.13.1 diff --git a/.riot/requirements/18147c2.txt b/.riot/requirements/18147c2.txt index 5c5f8a6a0fd..b959849683d 100644 --- a/.riot/requirements/18147c2.txt +++ b/.riot/requirements/18147c2.txt @@ -2,28 +2,29 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --no-annotate .riot/requirements/18147c2.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/18147c2.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 -pytest==8.1.1 -pytest-cov==5.0.0 +packaging==24.2 +pluggy==1.5.0 +pytest==8.3.5 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 +typing-extensions==4.13.1 diff --git a/.riot/requirements/1b09cab.txt b/.riot/requirements/1b09cab.txt index a8fd716e3c9..c38817ba445 100644 --- a/.riot/requirements/1b09cab.txt +++ b/.riot/requirements/1b09cab.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --config=pyproject.toml --no-annotate .riot/requirements/1b09cab.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1b09cab.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +anyio==4.5.2 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.6.1 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 pytest==7.4.4 pytest-cov==2.12.0 pytest-mock==2.0.0 pytest-randomly==3.15.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 -zipp==3.18.1 +tomli==2.2.1 +typing-extensions==4.13.1 +zipp==3.20.2 diff --git a/.riot/requirements/1becf29.txt b/.riot/requirements/1becf29.txt index 9a18af7d058..6ca058d4c97 100644 --- a/.riot/requirements/1becf29.txt +++ b/.riot/requirements/1becf29.txt @@ -2,31 +2,31 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --no-annotate --resolver=backtracking .riot/requirements/1becf29.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1becf29.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 pytest==7.4.4 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 +tomli==2.2.1 +typing-extensions==4.13.1 diff --git a/.riot/requirements/1cc7f49.txt b/.riot/requirements/1cc7f49.txt index 644fd59d910..e0c85193e9d 100644 --- a/.riot/requirements/1cc7f49.txt +++ b/.riot/requirements/1cc7f49.txt @@ -2,16 +2,16 @@ # This file is autogenerated by pip-compile with Python 3.11 # by the following command: # -# pip-compile --no-annotate .riot/requirements/1cc7f49.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1cc7f49.in # -attrs==24.3.0 -coverage[toml]==7.6.9 +attrs==25.3.0 +coverage[toml]==7.8.0 glob2==0.7 hypothesis==6.45.0 -iniconfig==2.0.0 -mako==1.3.8 +iniconfig==2.1.0 +mako==1.3.9 markupsafe==3.0.2 -mock==5.1.0 +mock==5.2.0 more-itertools==8.10.0 msgpack==1.1.0 opentracing==2.4.0 @@ -20,9 +20,9 @@ parse==1.20.2 parse-type==0.6.4 pluggy==1.5.0 py==1.11.0 -pytest==8.3.4 +pytest==8.3.5 pytest-bdd==6.0.1 -pytest-cov==6.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 pytest-randomly==3.16.0 six==1.17.0 diff --git a/.riot/requirements/1ce9a95.txt b/.riot/requirements/1ce9a95.txt index 363ae1fa333..a08b4eaa810 100644 --- a/.riot/requirements/1ce9a95.txt +++ b/.riot/requirements/1ce9a95.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --no-annotate .riot/requirements/1ce9a95.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1ce9a95.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.6.1 +exceptiongroup==1.2.2 glob2==0.7 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mako==1.3.2 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mako==1.3.9 markupsafe==2.1.5 -mock==5.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.7 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -parse==1.20.1 -parse-type==0.6.2 -pluggy==1.4.0 +packaging==24.2 +parse==1.20.2 +parse-type==0.6.4 +pluggy==1.5.0 py==1.11.0 -pytest==8.0.0 +pytest==8.3.5 pytest-bdd==4.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 +pytest-cov==5.0.0 +pytest-mock==3.14.0 pytest-randomly==3.15.0 -six==1.16.0 +six==1.17.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.20.2 diff --git a/.riot/requirements/1d44438.txt b/.riot/requirements/1d44438.txt index 5a2fbefacd8..fef2c21d5ea 100644 --- a/.riot/requirements/1d44438.txt +++ b/.riot/requirements/1d44438.txt @@ -2,16 +2,16 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --no-annotate .riot/requirements/1d44438.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1d44438.in # -attrs==24.3.0 -coverage[toml]==7.6.9 +attrs==25.3.0 +coverage[toml]==7.8.0 glob2==0.7 hypothesis==6.45.0 -iniconfig==2.0.0 -mako==1.3.8 +iniconfig==2.1.0 +mako==1.3.9 markupsafe==3.0.2 -mock==5.1.0 +mock==5.2.0 more-itertools==8.10.0 msgpack==1.1.0 opentracing==2.4.0 @@ -20,9 +20,9 @@ parse==1.20.2 parse-type==0.6.4 pluggy==1.5.0 py==1.11.0 -pytest==8.3.4 +pytest==8.3.5 pytest-bdd==6.0.1 -pytest-cov==6.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 pytest-randomly==3.16.0 six==1.17.0 diff --git a/.riot/requirements/1f42cb3.txt b/.riot/requirements/1f42cb3.txt index 2d3467ff27a..03ee4eebac9 100644 --- a/.riot/requirements/1f42cb3.txt +++ b/.riot/requirements/1f42cb3.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --config=pyproject.toml --no-annotate .riot/requirements/1f42cb3.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/1f42cb3.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +anyio==4.9.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 pytest==7.4.4 pytest-cov==2.12.0 pytest-mock==2.0.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 -zipp==3.18.1 +tomli==2.2.1 +typing-extensions==4.13.1 +zipp==3.21.0 diff --git a/.riot/requirements/2b9f1e7.txt b/.riot/requirements/2b9f1e7.txt index be8c122b5f8..a61a3048c55 100644 --- a/.riot/requirements/2b9f1e7.txt +++ b/.riot/requirements/2b9f1e7.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --no-annotate .riot/requirements/2b9f1e7.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/2b9f1e7.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 glob2==0.7 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mako==1.3.2 -markupsafe==2.1.5 -mock==5.1.0 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mako==1.3.9 +markupsafe==3.0.2 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.7 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -parse==1.20.1 -parse-type==0.6.2 -pluggy==1.4.0 +packaging==24.2 +parse==1.20.2 +parse-type==0.6.4 +pluggy==1.5.0 py==1.11.0 -pytest==8.0.0 +pytest==8.3.5 pytest-bdd==6.0.1 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-randomly==3.15.0 -six==1.16.0 +pytest-cov==6.1.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +six==1.17.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.21.0 diff --git a/.riot/requirements/3af9e27.txt b/.riot/requirements/3af9e27.txt index 09231897bd8..e9bcfa37b1a 100644 --- a/.riot/requirements/3af9e27.txt +++ b/.riot/requirements/3af9e27.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --no-annotate .riot/requirements/3af9e27.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/3af9e27.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +anyio==4.5.2 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.6.1 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 -pytest==8.1.1 +packaging==24.2 +pluggy==1.5.0 +pytest==8.3.5 pytest-cov==2.12.0 pytest-mock==2.0.0 pytest-randomly==3.15.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 -zipp==3.18.1 +tomli==2.2.1 +typing-extensions==4.13.1 +zipp==3.20.2 diff --git a/.riot/requirements/48eb599.txt b/.riot/requirements/48eb599.txt index cf67ac7deb3..c51c1cf9038 100644 --- a/.riot/requirements/48eb599.txt +++ b/.riot/requirements/48eb599.txt @@ -2,28 +2,29 @@ # This file is autogenerated by pip-compile with Python 3.12 # by the following command: # -# pip-compile --no-annotate .riot/requirements/48eb599.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/48eb599.in # -anyio==4.3.0 +anyio==4.9.0 asynctest==0.13.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 pytest==7.4.4 -pytest-cov==5.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 +typing-extensions==4.13.1 diff --git a/.riot/requirements/498209d.txt b/.riot/requirements/498209d.txt index b975548628c..1de41364459 100644 --- a/.riot/requirements/498209d.txt +++ b/.riot/requirements/498209d.txt @@ -4,19 +4,19 @@ # # pip-compile --allow-unsafe --no-annotate .riot/requirements/498209d.in # -attrs==24.3.0 -coverage[toml]==7.6.9 +attrs==25.3.0 +coverage[toml]==7.8.0 hypothesis==6.45.0 -iniconfig==2.0.0 -mock==5.1.0 +iniconfig==2.1.0 +mock==5.2.0 msgpack==1.1.0 opentracing==2.4.0 packaging==24.2 pluggy==1.5.0 py-cpuinfo==9.0.0 -pytest==8.3.4 +pytest==8.3.5 pytest-benchmark==4.0.0 -pytest-cov==6.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 pytest-randomly==3.16.0 sortedcontainers==2.4.0 diff --git a/.riot/requirements/7e7551c.txt b/.riot/requirements/7e7551c.txt index 945877903ec..3b929a2d254 100644 --- a/.riot/requirements/7e7551c.txt +++ b/.riot/requirements/7e7551c.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --no-annotate .riot/requirements/7e7551c.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/7e7551c.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.6.1 +exceptiongroup==1.2.2 glob2==0.7 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mako==1.3.2 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mako==1.3.9 markupsafe==2.1.5 -mock==5.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.7 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -parse==1.20.1 -parse-type==0.6.2 -pluggy==1.4.0 +packaging==24.2 +parse==1.20.2 +parse-type==0.6.4 +pluggy==1.5.0 py==1.11.0 -pytest==8.0.0 +pytest==8.3.5 pytest-bdd==6.0.1 -pytest-cov==4.1.0 -pytest-mock==3.12.0 +pytest-cov==5.0.0 +pytest-mock==3.14.0 pytest-randomly==3.15.0 -six==1.16.0 +six==1.17.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.20.2 diff --git a/.riot/requirements/8fd4efc.txt b/.riot/requirements/8fd4efc.txt index a7217c530cd..eea0c53e909 100644 --- a/.riot/requirements/8fd4efc.txt +++ b/.riot/requirements/8fd4efc.txt @@ -2,33 +2,33 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --config=pyproject.toml --no-annotate .riot/requirements/8fd4efc.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/8fd4efc.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage==7.4.4 -exceptiongroup==1.2.0 +anyio==4.9.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py==1.11.0 pytest==6.2.5 pytest-cov==2.9.0 pytest-mock==2.0.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 toml==0.10.2 -typing-extensions==4.11.0 -zipp==3.18.1 +typing-extensions==4.13.1 +zipp==3.21.0 diff --git a/.riot/requirements/91bec06.txt b/.riot/requirements/91bec06.txt index 15f0875ec11..12e28ed1fe1 100644 --- a/.riot/requirements/91bec06.txt +++ b/.riot/requirements/91bec06.txt @@ -2,26 +2,26 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --config=pyproject.toml --no-annotate .riot/requirements/91bec06.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/91bec06.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage==7.4.4 -exceptiongroup==1.2.0 +anyio==4.5.2 +attrs==25.3.0 +certifi==2025.1.31 +coverage==7.6.1 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py==1.11.0 pytest==6.2.5 pytest-cov==2.9.0 @@ -30,5 +30,5 @@ pytest-randomly==3.15.0 sniffio==1.3.1 sortedcontainers==2.4.0 toml==0.10.2 -typing-extensions==4.11.0 -zipp==3.18.1 +typing-extensions==4.13.1 +zipp==3.20.2 diff --git a/.riot/requirements/9b8c47e.txt b/.riot/requirements/9b8c47e.txt index 1786a038a59..45b01ee6080 100644 --- a/.riot/requirements/9b8c47e.txt +++ b/.riot/requirements/9b8c47e.txt @@ -2,25 +2,25 @@ # This file is autogenerated by pip-compile with Python 3.8 # by the following command: # -# pip-compile --no-annotate .riot/requirements/9b8c47e.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/9b8c47e.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.6.1 +exceptiongroup==1.2.2 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mock==5.1.0 -msgpack==1.0.7 +importlib-metadata==8.5.0 +iniconfig==2.1.0 +mock==5.2.0 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py-cpuinfo==9.0.0 -pytest==8.0.0 +pytest==8.3.5 pytest-benchmark==4.0.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 +pytest-cov==5.0.0 +pytest-mock==3.14.0 pytest-randomly==3.15.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.20.2 diff --git a/.riot/requirements/d03449e.txt b/.riot/requirements/d03449e.txt index 39414e29954..63a342f4339 100644 --- a/.riot/requirements/d03449e.txt +++ b/.riot/requirements/d03449e.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --config=pyproject.toml --no-annotate .riot/requirements/d03449e.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/d03449e.in # -anyio==4.3.0 -attrs==23.2.0 -certifi==2024.2.2 -coverage[toml]==7.4.4 -exceptiongroup==1.2.0 +anyio==4.9.0 +attrs==25.3.0 +certifi==2025.1.31 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 h11==0.14.0 -httpcore==1.0.5 -httpx==0.27.0 +httpcore==1.0.7 +httpx==0.28.1 hypothesis==6.45.0 -idna==3.7 -importlib-metadata==7.1.0 -iniconfig==2.0.0 -mock==5.1.0 +idna==3.10 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.8 +msgpack==1.1.0 opentracing==2.4.0 -packaging==24.0 -pluggy==1.4.0 -pytest==8.1.1 +packaging==24.2 +pluggy==1.5.0 +pytest==8.3.5 pytest-cov==2.12.0 pytest-mock==2.0.0 -pytest-randomly==3.15.0 +pytest-randomly==3.16.0 sniffio==1.3.1 sortedcontainers==2.4.0 -tomli==2.0.1 -typing-extensions==4.11.0 -zipp==3.18.1 +tomli==2.2.1 +typing-extensions==4.13.1 +zipp==3.21.0 diff --git a/.riot/requirements/db02b05.txt b/.riot/requirements/db02b05.txt index 77c96200bd2..7797eb6251f 100644 --- a/.riot/requirements/db02b05.txt +++ b/.riot/requirements/db02b05.txt @@ -2,25 +2,25 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --no-annotate .riot/requirements/db02b05.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/db02b05.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mock==5.1.0 -msgpack==1.0.7 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mock==5.2.0 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -pluggy==1.4.0 +packaging==24.2 +pluggy==1.5.0 py-cpuinfo==9.0.0 -pytest==8.0.0 +pytest==8.3.5 pytest-benchmark==4.0.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-randomly==3.15.0 +pytest-cov==6.1.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.21.0 diff --git a/.riot/requirements/e5cd460.txt b/.riot/requirements/e5cd460.txt index d14867cc689..bd89ea35b40 100644 --- a/.riot/requirements/e5cd460.txt +++ b/.riot/requirements/e5cd460.txt @@ -4,19 +4,19 @@ # # pip-compile --allow-unsafe --no-annotate .riot/requirements/e5cd460.in # -attrs==24.3.0 -coverage[toml]==7.6.9 +attrs==25.3.0 +coverage[toml]==7.8.0 hypothesis==6.45.0 -iniconfig==2.0.0 -mock==5.1.0 +iniconfig==2.1.0 +mock==5.2.0 msgpack==1.1.0 opentracing==2.4.0 packaging==24.2 pluggy==1.5.0 py-cpuinfo==9.0.0 -pytest==8.3.4 +pytest==8.3.5 pytest-benchmark==4.0.0 -pytest-cov==6.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 pytest-randomly==3.16.0 sortedcontainers==2.4.0 diff --git a/.riot/requirements/fb47988.txt b/.riot/requirements/fb47988.txt index e9cc2d8236d..26a2d9ff521 100644 --- a/.riot/requirements/fb47988.txt +++ b/.riot/requirements/fb47988.txt @@ -2,17 +2,17 @@ # This file is autogenerated by pip-compile with Python 3.10 # by the following command: # -# pip-compile --no-annotate .riot/requirements/fb47988.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/fb47988.in # -attrs==24.3.0 -coverage[toml]==7.6.9 +attrs==25.3.0 +coverage[toml]==7.8.0 exceptiongroup==1.2.2 glob2==0.7 hypothesis==6.45.0 -iniconfig==2.0.0 -mako==1.3.8 +iniconfig==2.1.0 +mako==1.3.9 markupsafe==3.0.2 -mock==5.1.0 +mock==5.2.0 more-itertools==8.10.0 msgpack==1.1.0 opentracing==2.4.0 @@ -21,9 +21,9 @@ parse==1.20.2 parse-type==0.6.4 pluggy==1.5.0 py==1.11.0 -pytest==8.3.4 +pytest==8.3.5 pytest-bdd==6.0.1 -pytest-cov==6.0.0 +pytest-cov==6.1.0 pytest-mock==3.14.0 pytest-randomly==3.16.0 six==1.17.0 diff --git a/.riot/requirements/ff88ab0.txt b/.riot/requirements/ff88ab0.txt index 69b41f473b8..806a7ab9961 100644 --- a/.riot/requirements/ff88ab0.txt +++ b/.riot/requirements/ff88ab0.txt @@ -2,32 +2,32 @@ # This file is autogenerated by pip-compile with Python 3.9 # by the following command: # -# pip-compile --no-annotate .riot/requirements/ff88ab0.in +# pip-compile --allow-unsafe --no-annotate .riot/requirements/ff88ab0.in # -attrs==23.2.0 -coverage[toml]==7.4.1 -exceptiongroup==1.2.0 +attrs==25.3.0 +coverage[toml]==7.8.0 +exceptiongroup==1.2.2 glob2==0.7 hypothesis==6.45.0 -importlib-metadata==7.0.1 -iniconfig==2.0.0 -mako==1.3.2 -markupsafe==2.1.5 -mock==5.1.0 +importlib-metadata==8.6.1 +iniconfig==2.1.0 +mako==1.3.9 +markupsafe==3.0.2 +mock==5.2.0 more-itertools==8.10.0 -msgpack==1.0.7 +msgpack==1.1.0 opentracing==2.4.0 -packaging==23.2 -parse==1.20.1 -parse-type==0.6.2 -pluggy==1.4.0 +packaging==24.2 +parse==1.20.2 +parse-type==0.6.4 +pluggy==1.5.0 py==1.11.0 -pytest==8.0.0 +pytest==8.3.5 pytest-bdd==4.1.0 -pytest-cov==4.1.0 -pytest-mock==3.12.0 -pytest-randomly==3.15.0 -six==1.16.0 +pytest-cov==6.1.0 +pytest-mock==3.14.0 +pytest-randomly==3.16.0 +six==1.17.0 sortedcontainers==2.4.0 -tomli==2.0.1 -zipp==3.17.0 +tomli==2.2.1 +zipp==3.21.0 diff --git a/ddtrace/contrib/internal/pytest/_plugin_v1.py b/ddtrace/contrib/internal/pytest/_plugin_v1.py deleted file mode 100644 index d45a925f773..00000000000 --- a/ddtrace/contrib/internal/pytest/_plugin_v1.py +++ /dev/null @@ -1,917 +0,0 @@ -""" -This custom pytest plugin implements tracing for pytest by using pytest hooks. The plugin registers tracing code -to be run at specific points during pytest execution. The most important hooks used are: - - * pytest_sessionstart: during pytest session startup, a custom trace filter is configured to the global tracer to - only send test spans, which are generated by the plugin. - * pytest_runtest_protocol: this wraps around the execution of a pytest test function, which we trace. Most span - tags are generated and added in this function. We also store the span on the underlying pytest test item to - retrieve later when we need to report test status/result. - * pytest_runtest_makereport: this hook is used to set the test status/result tag, including skipped tests and - expected failures. - -""" -from doctest import DocTest -import json -import os -from pathlib import Path -import re -from typing import Dict # noqa:F401 - -from _pytest.nodes import get_fslocation_from_item -import pytest - -import ddtrace -from ddtrace import DDTraceDeprecationWarning -from ddtrace.constants import SPAN_KIND -from ddtrace.contrib.internal.coverage.data import _coverage_data -from ddtrace.contrib.internal.coverage.patch import patch as patch_coverage -from ddtrace.contrib.internal.coverage.patch import run_coverage_report -from ddtrace.contrib.internal.coverage.patch import unpatch as unpatch_coverage -from ddtrace.contrib.internal.coverage.utils import _is_coverage_invoked_by_coverage_run -from ddtrace.contrib.internal.coverage.utils import _is_coverage_patched -from ddtrace.contrib.internal.pytest._utils import _extract_span -from ddtrace.contrib.internal.pytest._utils import _is_enabled_early -from ddtrace.contrib.internal.pytest._utils import _is_pytest_8_or_later -from ddtrace.contrib.internal.pytest._utils import _is_test_unskippable -from ddtrace.contrib.internal.pytest.constants import FRAMEWORK -from ddtrace.contrib.internal.pytest.constants import KIND -from ddtrace.contrib.internal.pytest.constants import XFAIL_REASON -from ddtrace.contrib.internal.pytest.plugin import is_enabled -from ddtrace.contrib.internal.unittest.patch import unpatch as unpatch_unittest -from ddtrace.ext import SpanTypes -from ddtrace.ext import test -from ddtrace.internal.ci_visibility import CIVisibility as _CIVisibility -from ddtrace.internal.ci_visibility.constants import EVENT_TYPE as _EVENT_TYPE -from ddtrace.internal.ci_visibility.constants import ITR_CORRELATION_ID_TAG_NAME -from ddtrace.internal.ci_visibility.constants import MODULE_ID as _MODULE_ID -from ddtrace.internal.ci_visibility.constants import MODULE_TYPE as _MODULE_TYPE -from ddtrace.internal.ci_visibility.constants import SESSION_ID as _SESSION_ID -from ddtrace.internal.ci_visibility.constants import SESSION_TYPE as _SESSION_TYPE -from ddtrace.internal.ci_visibility.constants import SKIPPED_BY_ITR_REASON -from ddtrace.internal.ci_visibility.constants import SUITE -from ddtrace.internal.ci_visibility.constants import SUITE_ID as _SUITE_ID -from ddtrace.internal.ci_visibility.constants import SUITE_TYPE as _SUITE_TYPE -from ddtrace.internal.ci_visibility.constants import TEST -from ddtrace.internal.ci_visibility.coverage import USE_DD_COVERAGE -from ddtrace.internal.ci_visibility.coverage import _module_has_dd_coverage_enabled -from ddtrace.internal.ci_visibility.coverage import _report_coverage_to_span -from ddtrace.internal.ci_visibility.coverage import _start_coverage -from ddtrace.internal.ci_visibility.coverage import _stop_coverage -from ddtrace.internal.ci_visibility.coverage import _switch_coverage_context -from ddtrace.internal.ci_visibility.telemetry.constants import TEST_FRAMEWORKS -from ddtrace.internal.ci_visibility.utils import _add_pct_covered_to_span -from ddtrace.internal.ci_visibility.utils import _add_start_end_source_file_path_data_to_span -from ddtrace.internal.ci_visibility.utils import _generate_fully_qualified_module_name -from ddtrace.internal.ci_visibility.utils import _generate_fully_qualified_test_name -from ddtrace.internal.ci_visibility.utils import get_relative_or_absolute_path_for_path -from ddtrace.internal.ci_visibility.utils import take_over_logger_stream_handler -from ddtrace.internal.constants import COMPONENT -from ddtrace.internal.coverage.code import ModuleCodeCollector -from ddtrace.internal.logger import get_logger -from ddtrace.internal.utils.formats import asbool -from ddtrace.internal.utils.inspection import undecorated -from ddtrace.vendor.debtcollector import deprecate - - -log = get_logger(__name__) - -_global_skipped_elements = 0 - -# COVER_SESSION is an experimental feature flag that provides full coverage (similar to coverage run), and is an -# experimental feature. It currently significantly increases test import time and should not be used. -COVER_SESSION = asbool(os.environ.get("_DD_COVER_SESSION", "false")) - - -def encode_test_parameter(parameter): - param_repr = repr(parameter) - # if the representation includes an id() we'll remove it - # because it isn't constant across executions - return re.sub(r" at 0[xX][0-9a-fA-F]+", "", param_repr) - - -def _is_pytest_cov_enabled(config) -> bool: - if not config.pluginmanager.get_plugin("pytest_cov"): - return False - cov_option = config.getoption("--cov", default=False) - nocov_option = config.getoption("--no-cov", default=False) - if nocov_option is True: - return False - if isinstance(cov_option, list) and cov_option == [True] and not nocov_option: - return True - return cov_option - - -def _store_span(item, span): - """Store span at `pytest.Item` instance.""" - item._datadog_span = span - - -def _extract_module_span(item): - """Extract span from `pytest.Item` instance.""" - return getattr(item, "_datadog_span_module", None) - - -def _extract_ancestor_module_span(item): - """Return the first ancestor module span found""" - while item: - module_span = _extract_module_span(item) or _extract_span(item) - if module_span is not None and module_span.name == "pytest.test_module": - return module_span - item = _get_parent(item) - - -def _extract_ancestor_suite_span(item): - """Return the first ancestor suite span found""" - while item: - suite_span = _extract_span(item) - if suite_span is not None and suite_span.name == "pytest.test_suite": - return suite_span - item = _get_parent(item) - - -def _store_module_span(item, span): - """Store span at `pytest.Item` instance.""" - item._datadog_span_module = span - - -def _mark_failed(item): - """Store test failed status at `pytest.Item` instance.""" - item_parent = _get_parent(item) - if item_parent: - _mark_failed(item_parent) - item._failed = True - - -def _check_failed(item): - """Extract test failed status from `pytest.Item` instance.""" - return getattr(item, "_failed", False) - - -def _mark_not_skipped(item): - """Mark test suite/module/session `pytest.Item` as not skipped.""" - item_parent = _get_parent(item) - if item_parent: - _mark_not_skipped(item_parent) - item._fully_skipped = False - - -def _mark_not_skipped(item): - """Mark test suite/module/session `pytest.Item` as not skipped.""" - - item_parent = _get_parent(item) - - if item_parent: - _mark_not_skipped(item_parent) - item._fully_skipped = False - - -def _get_parent(item): - """Fetches the nearest parent that is not a directory. - - This is introduced as a workaround for pytest 8.0's introduction pytest.Dir objects. - """ - if item is None or item.parent is None: - return None - - if _is_pytest_8_or_later(): - # In pytest 8.0, the parent of a Package can be another Package. In previous versions, the parent was always - # a session. - if isinstance(item, pytest.Package): - while item.parent is not None and not isinstance(item.parent, pytest.Session): - item = item.parent - return item.parent - - while item.parent is not None and isinstance(item.parent, pytest.Dir): - item = item.parent - - return item.parent - - -def _mark_test_forced(test_item): - # type: (pytest.Test) -> None - test_span = _extract_span(test_item) - test_span.set_tag_str(test.ITR_FORCED_RUN, "true") - - suite_span = _extract_ancestor_suite_span(test_item) - suite_span.set_tag_str(test.ITR_FORCED_RUN, "true") - - module_span = _extract_ancestor_module_span(test_item) - module_span.set_tag_str(test.ITR_FORCED_RUN, "true") - - session_span = _extract_span(test_item.session) - session_span.set_tag_str(test.ITR_FORCED_RUN, "true") - - -def _mark_test_unskippable(test_item): - # type: (pytest.Test) -> None - test_span = _extract_span(test_item) - test_span.set_tag_str(test.ITR_UNSKIPPABLE, "true") - - suite_span = _extract_ancestor_suite_span(test_item) - suite_span.set_tag_str(test.ITR_UNSKIPPABLE, "true") - - module_span = _extract_ancestor_module_span(test_item) - module_span.set_tag_str(test.ITR_UNSKIPPABLE, "true") - - session_span = _extract_span(test_item.session) - session_span.set_tag_str(test.ITR_UNSKIPPABLE, "true") - - -def _check_fully_skipped(item): - """Check if test suite/module/session `pytest.Item` has `_fully_skipped` marker.""" - return getattr(item, "_fully_skipped", True) - - -def _mark_test_status(item, span): - """ - Given a `pytest.Item`, determine and set the test status of the corresponding span. - """ - item_parent = _get_parent(item) - - # If any child has failed, mark span as failed. - if _check_failed(item): - status = test.Status.FAIL.value - if item_parent: - _mark_failed(item_parent) - _mark_not_skipped(item_parent) - # If all children have been skipped, mark span as skipped. - elif _check_fully_skipped(item): - status = test.Status.SKIP.value - else: - status = test.Status.PASS.value - if item_parent: - _mark_not_skipped(item_parent) - span.set_tag_str(test.STATUS, status) - - -def _extract_reason(call): - if call.excinfo is not None: - return call.excinfo.value - - -def _get_pytest_command(config): - """Extract and re-create pytest session command from pytest config.""" - command = "pytest" - if getattr(config, "invocation_params", None): - command += " {}".format(" ".join(config.invocation_params.args)) - return command - - -def _get_module_path(item): - """Extract module path from a `pytest.Item` instance.""" - # type (pytest.Item) -> str - if not isinstance(item, (pytest.Package, pytest.Module)): - return None - - if _is_pytest_8_or_later() and isinstance(item, pytest.Package): - module_path = item.nodeid - - else: - module_path = item.nodeid.rpartition("/")[0] - - return module_path - - -def _module_is_package(pytest_package_item=None, pytest_module_item=None): - # Pytest 8+ module items have a pytest.Dir object as their parent instead of the session object - if _is_pytest_8_or_later(): - return isinstance(pytest_module_item.parent, pytest.Package) - - if pytest_package_item is None and pytest_module_item is not None: - return False - return True - - -def _start_test_module_span(item): - """ - Starts a test module span at the start of a new pytest test package. - Note that ``item`` is a ``pytest.Item`` object referencing the test being run. - """ - pytest_module_item = _find_pytest_item(item, pytest.Module) - pytest_package_item = _find_pytest_item(pytest_module_item, pytest.Package) - - is_package = _module_is_package(pytest_package_item, pytest_module_item) - - if is_package: - span_target_item = pytest_package_item - else: - span_target_item = pytest_module_item - - test_session_span = _extract_span(item.session) - test_module_span = _CIVisibility._instance.tracer._start_span( - "pytest.test_module", - service=_CIVisibility._instance._service, - span_type=SpanTypes.TEST, - activate=True, - child_of=test_session_span, - ) - test_module_span.set_tag_str(COMPONENT, "pytest") - test_module_span.set_tag_str(SPAN_KIND, KIND) - test_module_span.set_tag_str(test.FRAMEWORK, FRAMEWORK) - test_module_span.set_tag_str(test.FRAMEWORK_VERSION, pytest.__version__) - test_module_span.set_tag_str(test.COMMAND, _get_pytest_command(item.config)) - test_module_span.set_tag_str(_EVENT_TYPE, _MODULE_TYPE) - if test_session_span: - test_module_span.set_tag_str(_SESSION_ID, str(test_session_span.span_id)) - test_module_span.set_tag_str(_MODULE_ID, str(test_module_span.span_id)) - test_module_span.set_tag_str(test.MODULE, item.config.hook.pytest_ddtrace_get_item_module_name(item=item)) - test_module_span.set_tag_str(test.MODULE_PATH, _get_module_path(span_target_item)) - if is_package: - _store_span(span_target_item, test_module_span) - else: - _store_module_span(span_target_item, test_module_span) - - test_module_span.set_tag_str( - test.ITR_TEST_CODE_COVERAGE_ENABLED, - "true" if _CIVisibility._instance._collect_coverage_enabled else "false", - ) - - if _CIVisibility.test_skipping_enabled(): - test_module_span.set_tag_str(test.ITR_TEST_SKIPPING_ENABLED, "true") - test_module_span.set_tag( - test.ITR_TEST_SKIPPING_TYPE, SUITE if _CIVisibility._instance._suite_skipping_mode else TEST - ) - test_module_span.set_tag_str(test.ITR_TEST_SKIPPING_TESTS_SKIPPED, "false") - test_module_span.set_tag_str(test.ITR_DD_CI_ITR_TESTS_SKIPPED, "false") - test_module_span.set_tag_str(test.ITR_FORCED_RUN, "false") - test_module_span.set_tag_str(test.ITR_UNSKIPPABLE, "false") - else: - test_module_span.set_tag(test.ITR_TEST_SKIPPING_ENABLED, "false") - - return test_module_span, is_package - - -def _start_test_suite_span(item, test_module_span, should_enable_coverage=False): - """ - Starts a test suite span at the start of a new pytest test module. - """ - pytest_module_item = _find_pytest_item(item, pytest.Module) - test_session_span = _extract_span(pytest_module_item.session) - if test_module_span is None and isinstance(pytest_module_item.parent, pytest.Package): - test_module_span = _extract_span(pytest_module_item.parent) - parent_span = test_module_span - if parent_span is None: - parent_span = test_session_span - - test_suite_span = _CIVisibility._instance.tracer._start_span( - "pytest.test_suite", - service=_CIVisibility._instance._service, - span_type=SpanTypes.TEST, - activate=True, - child_of=parent_span, - ) - test_suite_span.set_tag_str(COMPONENT, "pytest") - test_suite_span.set_tag_str(SPAN_KIND, KIND) - test_suite_span.set_tag_str(test.FRAMEWORK, FRAMEWORK) - test_suite_span.set_tag_str(test.FRAMEWORK_VERSION, pytest.__version__) - test_suite_span.set_tag_str(test.COMMAND, _get_pytest_command(pytest_module_item.config)) - test_suite_span.set_tag_str(_EVENT_TYPE, _SUITE_TYPE) - if test_session_span: - test_suite_span.set_tag_str(_SESSION_ID, str(test_session_span.span_id)) - test_suite_span.set_tag_str(_SUITE_ID, str(test_suite_span.span_id)) - test_module_path = "" - if test_module_span is not None: - test_suite_span.set_tag_str(_MODULE_ID, str(test_module_span.span_id)) - test_suite_span.set_tag_str(test.MODULE, test_module_span.get_tag(test.MODULE)) - test_module_path = test_module_span.get_tag(test.MODULE_PATH) - test_suite_span.set_tag_str(test.MODULE_PATH, test_module_path) - test_suite_name = item.config.hook.pytest_ddtrace_get_item_suite_name(item=item) - test_suite_span.set_tag_str(test.SUITE, test_suite_name) - _store_span(pytest_module_item, test_suite_span) - - if should_enable_coverage and _module_has_dd_coverage_enabled(pytest): - fqn_module = _generate_fully_qualified_module_name(test_module_path, test_suite_name) - _switch_coverage_context(pytest._dd_coverage, fqn_module, TEST_FRAMEWORKS.PYTEST) - return test_suite_span - - -def _find_pytest_item(item, pytest_item_type): - """ - Given a `pytest.Item`, traverse upwards until we find a specified `pytest.Package` or `pytest.Module` item, - or return None. - """ - if item is None: - return None - if pytest_item_type not in [pytest.Package, pytest.Module]: - return None - parent = _get_parent(item) - while not isinstance(parent, pytest_item_type) and parent is not None: - parent = parent.parent - return parent - - -def _get_test_class_hierarchy(item): - """ - Given a `pytest.Item` function item, traverse upwards to collect and return a string listing the - test class hierarchy, or an empty string if there are no test classes. - """ - parent = _get_parent(item) - test_class_hierarchy = [] - while parent is not None: - if isinstance(parent, pytest.Class): - test_class_hierarchy.insert(0, parent.name) - parent = parent.parent - return ".".join(test_class_hierarchy) - - -def pytest_load_initial_conftests(early_config, parser, args): - if _is_enabled_early(early_config): - # Enables experimental use of ModuleCodeCollector for coverage collection. - from ddtrace.internal.ci_visibility.coverage import USE_DD_COVERAGE - from ddtrace.internal.logger import get_logger - - log = get_logger(__name__) - - # Freezegun is proactively patched to avoid it interfering with internal timing - ddtrace.patch(freezegun=True) - - COVER_SESSION = asbool(os.environ.get("_DD_COVER_SESSION", "false")) - - if USE_DD_COVERAGE: - from ddtrace.ext.git import extract_workspace_path - from ddtrace.internal.coverage.code import ModuleCodeCollector - from ddtrace.internal.coverage.installer import install - - try: - workspace_path = Path(extract_workspace_path()) - except (ValueError, FileNotFoundError): - workspace_path = Path(os.getcwd()) - - log.warning("Installing ModuleCodeCollector with include_paths=%s", [workspace_path]) - - install(include_paths=[workspace_path], collect_import_time_coverage=True) - if COVER_SESSION: - ModuleCodeCollector.start_coverage() - else: - if COVER_SESSION: - log.warning( - "_DD_COVER_SESSION must be used with _DD_USE_INTERNAL_COVERAGE but not DD_CIVISIBILITY_ITR_ENABLED" - ) - - -def pytest_configure(config): - deprecate( - "this version of the pytest ddtrace plugin is deprecated", - message="remove _DD_PYTEST_USE_LEGACY_PLUGIN from your environment to use the currently supported version.", - category=DDTraceDeprecationWarning, - ) - unpatch_unittest() - if is_enabled(config): - ddtrace.config.test_visibility._itr_skipping_ignore_parameters = True - take_over_logger_stream_handler() - _CIVisibility.enable(config=ddtrace.config.pytest) - if _is_pytest_cov_enabled(config): - patch_coverage() - - -def pytest_sessionstart(session): - if _CIVisibility.enabled: - log.debug("CI Visibility enabled - starting test session") - global _global_skipped_elements - _global_skipped_elements = 0 - - workspace_path = _CIVisibility.get_workspace_path() - if workspace_path is None: - workspace_path = session.config.rootdir - - session.config._dd_workspace_path = workspace_path - - test_session_span = _CIVisibility._instance.tracer.trace( - "pytest.test_session", - service=_CIVisibility._instance._service, - span_type=SpanTypes.TEST, - ) - test_command = _get_pytest_command(session.config) - test_session_span.set_tag_str(COMPONENT, "pytest") - test_session_span.set_tag_str(SPAN_KIND, KIND) - test_session_span.set_tag_str(test.FRAMEWORK, FRAMEWORK) - test_session_span.set_tag_str(test.FRAMEWORK_VERSION, pytest.__version__) - test_session_span.set_tag_str(_EVENT_TYPE, _SESSION_TYPE) - test_session_span.set_tag_str(test.COMMAND, test_command) - test_session_span.set_tag_str(_SESSION_ID, str(test_session_span.span_id)) - - _CIVisibility.set_test_session_name(test_command=test_command) - - if _CIVisibility.test_skipping_enabled(): - test_session_span.set_tag_str(test.ITR_TEST_SKIPPING_ENABLED, "true") - test_session_span.set_tag( - test.ITR_TEST_SKIPPING_TYPE, SUITE if _CIVisibility._instance._suite_skipping_mode else TEST - ) - test_session_span.set_tag(test.ITR_TEST_SKIPPING_TESTS_SKIPPED, "false") - test_session_span.set_tag(test.ITR_DD_CI_ITR_TESTS_SKIPPED, "false") - test_session_span.set_tag_str(test.ITR_FORCED_RUN, "false") - test_session_span.set_tag_str(test.ITR_UNSKIPPABLE, "false") - else: - test_session_span.set_tag_str(test.ITR_TEST_SKIPPING_ENABLED, "false") - test_session_span.set_tag_str( - test.ITR_TEST_CODE_COVERAGE_ENABLED, - "true" if _CIVisibility._instance._collect_coverage_enabled else "false", - ) - if _is_coverage_invoked_by_coverage_run(): - patch_coverage() - if _CIVisibility._instance._collect_coverage_enabled and not _module_has_dd_coverage_enabled( - pytest, silent_mode=True - ): - pytest._dd_coverage = _start_coverage(session.config.rootdir) - - _store_span(session, test_session_span) - - -def pytest_sessionfinish(session, exitstatus): - if _CIVisibility.enabled: - log.debug("CI Visibility enabled - finishing test session") - test_session_span = _extract_span(session) - if test_session_span is not None: - if _CIVisibility.test_skipping_enabled(): - test_session_span.set_metric(test.ITR_TEST_SKIPPING_COUNT, _global_skipped_elements) - _mark_test_status(session, test_session_span) - pytest_cov_status = _is_pytest_cov_enabled(session.config) - invoked_by_coverage_run_status = _is_coverage_invoked_by_coverage_run() - if _is_coverage_patched() and (pytest_cov_status or invoked_by_coverage_run_status): - if invoked_by_coverage_run_status and not pytest_cov_status: - run_coverage_report() - _add_pct_covered_to_span(_coverage_data, test_session_span) - unpatch_coverage() - test_session_span.finish() - _CIVisibility.disable() - - -def pytest_collection_modifyitems(session, config, items): - if _CIVisibility.test_skipping_enabled(): - skip = pytest.mark.skip(reason=SKIPPED_BY_ITR_REASON) - - items_to_skip_by_module = {} - current_suite_has_unskippable_test = False - - for item in items: - test_is_unskippable = _is_test_unskippable(item) - - item_name = item.config.hook.pytest_ddtrace_get_item_test_name(item=item) - - if test_is_unskippable: - log.debug( - "Test %s in module %s (file: %s ) is marked as unskippable", - item_name, - item.module.__name__, - item.module.__file__, - ) - item._dd_itr_test_unskippable = True - - # Due to suite skipping mode, defer adding ITR skip marker until unskippable status of the suite has - # been fully resolved because Pytest markers cannot be dynamically removed - if _CIVisibility._instance._suite_skipping_mode: - if item.module not in items_to_skip_by_module: - items_to_skip_by_module[item.module] = [] - current_suite_has_unskippable_test = False - - if test_is_unskippable and not current_suite_has_unskippable_test: - current_suite_has_unskippable_test = True - # Retroactively mark collected tests as forced: - for item_to_skip in items_to_skip_by_module[item.module]: - item_to_skip._dd_itr_forced = True - items_to_skip_by_module[item.module] = [] - - if _CIVisibility._instance._should_skip_path(str(get_fslocation_from_item(item)[0]), item_name): - if test_is_unskippable or ( - _CIVisibility._instance._suite_skipping_mode and current_suite_has_unskippable_test - ): - item._dd_itr_forced = True - else: - items_to_skip_by_module.setdefault(item.module, []).append(item) - - # Mark remaining tests that should be skipped - for items_to_skip in items_to_skip_by_module.values(): - for item_to_skip in items_to_skip: - item_to_skip.add_marker(skip) - - -@pytest.hookimpl(tryfirst=True, hookwrapper=True) -def pytest_runtest_protocol(item, nextitem): - if not _CIVisibility.enabled: - yield - return - - is_skipped = bool( - item.get_closest_marker("skip") - or any([marker for marker in item.iter_markers(name="skipif") if marker.args[0] is True]) - ) - is_skipped_by_itr = bool( - is_skipped - and any( - [ - marker - for marker in item.iter_markers(name="skip") - if "reason" in marker.kwargs and marker.kwargs["reason"] == SKIPPED_BY_ITR_REASON - ] - ) - ) - - test_session_span = _extract_span(item.session) - - pytest_module_item = _find_pytest_item(item, pytest.Module) - pytest_package_item = _find_pytest_item(pytest_module_item, pytest.Package) - - module_is_package = True - - test_module_span = _extract_span(pytest_package_item) - if not test_module_span: - test_module_span = _extract_module_span(pytest_module_item) - if test_module_span: - module_is_package = False - - if test_module_span is None: - test_module_span, module_is_package = _start_test_module_span(item) - - if _CIVisibility.test_skipping_enabled() and test_module_span.get_metric(test.ITR_TEST_SKIPPING_COUNT) is None: - test_module_span.set_tag( - test.ITR_TEST_SKIPPING_TYPE, SUITE if _CIVisibility._instance._suite_skipping_mode else TEST - ) - test_module_span.set_metric(test.ITR_TEST_SKIPPING_COUNT, 0) - - test_suite_span = _extract_ancestor_suite_span(item) - if pytest_module_item is not None and test_suite_span is None: - # Start coverage for the test suite if coverage is enabled - # In ITR suite skipping mode, all tests in a skipped suite should be marked - # as skipped - test_suite_span = _start_test_suite_span( - item, - test_module_span, - should_enable_coverage=( - _CIVisibility._instance._suite_skipping_mode - and _CIVisibility._instance._collect_coverage_enabled - and not is_skipped_by_itr - ), - ) - - if is_skipped_by_itr: - test_module_span._metrics[test.ITR_TEST_SKIPPING_COUNT] += 1 - global _global_skipped_elements - _global_skipped_elements += 1 - test_module_span.set_tag_str(test.ITR_TEST_SKIPPING_TESTS_SKIPPED, "true") - test_module_span.set_tag_str(test.ITR_DD_CI_ITR_TESTS_SKIPPED, "true") - - test_session_span.set_tag_str(test.ITR_TEST_SKIPPING_TESTS_SKIPPED, "true") - test_session_span.set_tag_str(test.ITR_DD_CI_ITR_TESTS_SKIPPED, "true") - - with _CIVisibility._instance.tracer._start_span( - ddtrace.config.pytest.operation_name, - service=_CIVisibility._instance._service, - resource=item.nodeid, - span_type=SpanTypes.TEST, - activate=True, - ) as span: - span.set_tag_str(COMPONENT, "pytest") - span.set_tag_str(SPAN_KIND, KIND) - span.set_tag_str(test.FRAMEWORK, FRAMEWORK) - span.set_tag_str(_EVENT_TYPE, SpanTypes.TEST) - test_name = item.config.hook.pytest_ddtrace_get_item_test_name(item=item) - test_module_path = test_module_span.get_tag(test.MODULE_PATH) - span.set_tag_str(test.NAME, test_name) - span.set_tag_str(test.COMMAND, _get_pytest_command(item.config)) - if test_session_span: - span.set_tag_str(_SESSION_ID, str(test_session_span.span_id)) - - span.set_tag_str(_MODULE_ID, str(test_module_span.span_id)) - span.set_tag_str(test.MODULE, test_module_span.get_tag(test.MODULE)) - span.set_tag_str(test.MODULE_PATH, test_module_path) - - span.set_tag_str(_SUITE_ID, str(test_suite_span.span_id)) - test_class_hierarchy = _get_test_class_hierarchy(item) - if test_class_hierarchy: - span.set_tag_str(test.CLASS_HIERARCHY, test_class_hierarchy) - if hasattr(item, "dtest") and isinstance(item.dtest, DocTest): - test_suite_name = "{}.py".format(item.dtest.globs["__name__"]) - span.set_tag_str(test.SUITE, test_suite_name) - else: - test_suite_name = test_suite_span.get_tag(test.SUITE) - span.set_tag_str(test.SUITE, test_suite_name) - - span.set_tag_str(test.TYPE, SpanTypes.TEST) - span.set_tag_str(test.FRAMEWORK_VERSION, pytest.__version__) - - if item.location and item.location[0]: - _CIVisibility.set_codeowners_of(item.location[0], span=span) - if hasattr(item, "_obj"): - item_path = Path(item.path if hasattr(item, "path") else item.fspath) - test_method_object = undecorated(item._obj, item.name, item_path) - _add_start_end_source_file_path_data_to_span( - span, - test_method_object, - test_name, - getattr(item.session.config, "_dd_workspace_path", item.config.rootdir), - ) - - # We preemptively set FAIL as a status, because if pytest_runtest_makereport is not called - # (where the actual test status is set), it means there was a pytest error - span.set_tag_str(test.STATUS, test.Status.FAIL.value) - - # Parameterized test cases will have a `callspec` attribute attached to the pytest Item object. - # Pytest docs: https://docs.pytest.org/en/6.2.x/reference.html#pytest.Function - if getattr(item, "callspec", None): - parameters = {"arguments": {}, "metadata": {}} # type: Dict[str, Dict[str, str]] - for param_name, param_val in item.callspec.params.items(): - try: - parameters["arguments"][param_name] = encode_test_parameter(param_val) - except Exception: - parameters["arguments"][param_name] = "Could not encode" - log.warning("Failed to encode %r", param_name, exc_info=True) - span.set_tag_str(test.PARAMETERS, json.dumps(parameters)) - - if ITR_CORRELATION_ID_TAG_NAME in _CIVisibility._instance._itr_meta: - if _CIVisibility._instance._suite_skipping_mode: - test_suite_span.set_tag_str( - ITR_CORRELATION_ID_TAG_NAME, _CIVisibility._instance._itr_meta[ITR_CORRELATION_ID_TAG_NAME] - ) - else: - span.set_tag_str( - ITR_CORRELATION_ID_TAG_NAME, _CIVisibility._instance._itr_meta[ITR_CORRELATION_ID_TAG_NAME] - ) - - markers = [marker.kwargs for marker in item.iter_markers(name="dd_tags")] - for tags in markers: - span.set_tags(tags) - _store_span(item, span) - - # Items are marked ITR-unskippable regardless of other unrelateed skipping status - if getattr(item, "_dd_itr_test_unskippable", False) or getattr(item, "_dd_itr_suite_unskippable", False): - _mark_test_unskippable(item) - if not is_skipped: - if getattr(item, "_dd_itr_forced", False): - _mark_test_forced(item) - - coverage_per_test = ( - not _CIVisibility._instance._suite_skipping_mode - and _CIVisibility._instance._collect_coverage_enabled - and not is_skipped - ) - root_directory = str(item.config.rootdir) - if coverage_per_test and _module_has_dd_coverage_enabled(pytest): - fqn_test = _generate_fully_qualified_test_name(test_module_path, test_suite_name, test_name) - _switch_coverage_context(pytest._dd_coverage, fqn_test, TEST_FRAMEWORKS.PYTEST) - # Run the actual test - yield - - # Finish coverage for the test suite if coverage is enabled - if coverage_per_test and _module_has_dd_coverage_enabled(pytest): - _report_coverage_to_span(pytest._dd_coverage, span, root_directory, TEST_FRAMEWORKS.PYTEST) - - nextitem_pytest_module_item = _find_pytest_item(nextitem, pytest.Module) - if nextitem is None or nextitem_pytest_module_item != pytest_module_item and not test_suite_span.finished: - _mark_test_status(pytest_module_item, test_suite_span) - # Finish coverage for the test suite if coverage is enabled - # In ITR suite skipping mode, all tests in a skipped suite should be marked - # as skipped - if ( - _CIVisibility._instance._suite_skipping_mode - and _CIVisibility._instance._collect_coverage_enabled - and not is_skipped_by_itr - and _module_has_dd_coverage_enabled(pytest) - ): - _report_coverage_to_span(pytest._dd_coverage, test_suite_span, root_directory) - test_suite_span.finish() - - if not module_is_package: - test_module_span.set_tag_str(test.STATUS, test_suite_span.get_tag(test.STATUS)) - test_module_span.finish() - else: - nextitem_pytest_package_item = _find_pytest_item(nextitem, pytest.Package) - if ( - nextitem is None - or nextitem_pytest_package_item != pytest_package_item - and not test_module_span.finished - ): - _mark_test_status(pytest_package_item, test_module_span) - test_module_span.finish() - - if ( - nextitem is None - and _CIVisibility._instance._collect_coverage_enabled - and _module_has_dd_coverage_enabled(pytest) - ): - _stop_coverage(pytest) - - -@pytest.hookimpl(hookwrapper=True) -def pytest_runtest_makereport(item, call): - """Store outcome for tracing.""" - outcome = yield - - if not _CIVisibility.enabled: - return - - span = _extract_span(item) - if span is None: - return - - is_setup_or_teardown = call.when == "setup" or call.when == "teardown" - has_exception = call.excinfo is not None - - if is_setup_or_teardown and not has_exception: - return - - result = outcome.get_result() - xfail = hasattr(result, "wasxfail") or "xfail" in result.keywords - has_skip_keyword = any(x in result.keywords for x in ["skip", "skipif", "skipped"]) - - # If run with --runxfail flag, tests behave as if they were not marked with xfail, - # that's why no XFAIL_REASON or test.RESULT tags will be added. - if result.skipped: - if xfail and not has_skip_keyword: - # XFail tests that fail are recorded skipped by pytest, should be passed instead - span.set_tag_str(test.STATUS, test.Status.PASS.value) - _mark_not_skipped(_get_parent(item)) - if not item.config.option.runxfail: - span.set_tag_str(test.RESULT, test.Status.XFAIL.value) - span.set_tag_str(XFAIL_REASON, getattr(result, "wasxfail", "XFail")) - else: - span.set_tag_str(test.STATUS, test.Status.SKIP.value) - reason = _extract_reason(call) - if reason is not None: - span.set_tag_str(test.SKIP_REASON, str(reason)) - if str(reason) == SKIPPED_BY_ITR_REASON: - if _CIVisibility._instance._suite_skipping_mode: - suite_span = _extract_ancestor_suite_span(item) - if suite_span is not None: - suite_span.set_tag_str(test.ITR_SKIPPED, "true") - span.set_tag_str(test.ITR_SKIPPED, "true") - elif result.passed: - _mark_not_skipped(_get_parent(item)) - span.set_tag_str(test.STATUS, test.Status.PASS.value) - if xfail and not has_skip_keyword and not item.config.option.runxfail: - # XPass (strict=False) are recorded passed by pytest - span.set_tag_str(XFAIL_REASON, getattr(result, "wasxfail", "XFail")) - span.set_tag_str(test.RESULT, test.Status.XPASS.value) - else: - # Store failure in test suite `pytest.Item` to propagate to test suite spans - _mark_failed(_get_parent(item)) - _mark_not_skipped(_get_parent(item)) - span.set_tag_str(test.STATUS, test.Status.FAIL.value) - if xfail and not has_skip_keyword and not item.config.option.runxfail: - # XPass (strict=True) are recorded failed by pytest, longrepr contains reason - span.set_tag_str(XFAIL_REASON, getattr(result, "longrepr", "XFail")) - span.set_tag_str(test.RESULT, test.Status.XPASS.value) - if call.excinfo: - span.set_exc_info(call.excinfo.type, call.excinfo.value, call.excinfo.tb) - - -@pytest.hookimpl(trylast=True) -def pytest_ddtrace_get_item_module_name(item): - pytest_module_item = _find_pytest_item(item, pytest.Module) - pytest_package_item = _find_pytest_item(pytest_module_item, pytest.Package) - - if _module_is_package(pytest_package_item, pytest_module_item): - if _is_pytest_8_or_later(): - # pytest 8.0.0 no longer treats Packages as Module/File, so we replicate legacy behavior by - # concatenating parent package names in reverse until we hit a non-Package-type item - # https://github.com/pytest-dev/pytest/issues/11137 - package_names = [] - current_package = pytest_package_item - while isinstance(current_package, pytest.Package): - package_names.append(str(current_package.name)) - current_package = current_package.parent - - return ".".join(package_names[::-1]) - - return pytest_package_item.module.__name__ - - return pytest_module_item.nodeid.rpartition("/")[0].replace("/", ".") - - -@pytest.hookimpl(trylast=True) -def pytest_ddtrace_get_item_suite_name(item): - """ - Extract suite name from a `pytest.Item` instance. - If the module path doesn't exist, the suite path will be reported in full. - """ - pytest_module_item = _find_pytest_item(item, pytest.Module) - test_module_path = _get_module_path(pytest_module_item) - if test_module_path: - if not pytest_module_item.nodeid.startswith(test_module_path): - log.warning("Suite path is not under module path: '%s' '%s'", pytest_module_item.nodeid, test_module_path) - return get_relative_or_absolute_path_for_path(pytest_module_item.nodeid, test_module_path) - return pytest_module_item.nodeid - - -@pytest.hookimpl(trylast=True) -def pytest_ddtrace_get_item_test_name(item): - """Extract name from item, prepending class if desired""" - if hasattr(item, "cls") and item.cls: - if item.config.getoption("ddtrace-include-class-name") or item.config.getini("ddtrace-include-class-name"): - return "%s.%s" % (item.cls.__name__, item.name) - return item.name - - -@pytest.hookimpl(trylast=True) -def pytest_terminal_summary(terminalreporter, exitstatus, config): - # Reports coverage if experimental session-level coverage is enabled. - if USE_DD_COVERAGE and COVER_SESSION: - workspace_path = getattr(config, "_dd_workspace_path", None) - if workspace_path is None: - workspace_path = Path(os.getcwd()) - - ModuleCodeCollector.report(workspace_path) - try: - ModuleCodeCollector.write_json_report_to_file("dd_coverage.json", workspace_path) - except Exception: - log.debug("Failed to write coverage report to file", exc_info=True) diff --git a/ddtrace/contrib/internal/pytest/_plugin_v2.py b/ddtrace/contrib/internal/pytest/_plugin_v2.py index eb415d08667..56dcc5a8f06 100644 --- a/ddtrace/contrib/internal/pytest/_plugin_v2.py +++ b/ddtrace/contrib/internal/pytest/_plugin_v2.py @@ -15,8 +15,6 @@ from ddtrace.contrib.internal.coverage.utils import _is_coverage_invoked_by_coverage_run from ddtrace.contrib.internal.coverage.utils import _is_coverage_patched from ddtrace.contrib.internal.pytest._benchmark_utils import _set_benchmark_data_from_item -from ddtrace.contrib.internal.pytest._plugin_v1 import _extract_reason -from ddtrace.contrib.internal.pytest._plugin_v1 import _is_pytest_cov_enabled from ddtrace.contrib.internal.pytest._types import _pytest_report_teststatus_return_type from ddtrace.contrib.internal.pytest._types import pytest_CallInfo from ddtrace.contrib.internal.pytest._types import pytest_Config @@ -40,7 +38,6 @@ from ddtrace.contrib.internal.pytest.constants import FRAMEWORK from ddtrace.contrib.internal.pytest.constants import USER_PROPERTY_QUARANTINED from ddtrace.contrib.internal.pytest.constants import XFAIL_REASON -from ddtrace.contrib.internal.pytest.plugin import is_enabled from ddtrace.contrib.internal.unittest.patch import unpatch as unpatch_unittest from ddtrace.ext import test from ddtrace.ext.test_visibility import ITR_SKIPPING_LEVEL @@ -99,6 +96,11 @@ DISABLED_BY_TEST_MANAGEMENT_REASON = "Flaky test is disabled by Datadog" +def is_enabled(config): + """Check if the ddtrace plugin is enabled.""" + return (config.getoption("ddtrace") or config.getini("ddtrace")) and not config.getoption("no-ddtrace") + + def _handle_itr_should_skip(item, test_id) -> bool: """Checks whether a test should be skipped @@ -742,3 +744,20 @@ def pytest_ddtrace_get_item_test_name(item): """Extract name from item, prepending class if desired""" names = _get_names_from_item(item) return names.test + + +def _extract_reason(call): + if call.excinfo is not None: + return call.excinfo.value + + +def _is_pytest_cov_enabled(config) -> bool: + if not config.pluginmanager.get_plugin("pytest_cov"): + return False + cov_option = config.getoption("--cov", default=False) + nocov_option = config.getoption("--no-cov", default=False) + if nocov_option is True: + return False + if isinstance(cov_option, list) and cov_option == [True] and not nocov_option: + return True + return cov_option diff --git a/ddtrace/contrib/internal/pytest/_utils.py b/ddtrace/contrib/internal/pytest/_utils.py index 09f843f0240..f769e6e9757 100644 --- a/ddtrace/contrib/internal/pytest/_utils.py +++ b/ddtrace/contrib/internal/pytest/_utils.py @@ -23,7 +23,6 @@ from ddtrace.internal.test_visibility._internal_item_ids import InternalTestId from ddtrace.internal.test_visibility.api import InternalTest from ddtrace.internal.utils.cache import cached -from ddtrace.internal.utils.formats import asbool from ddtrace.internal.utils.inspection import undecorated @@ -31,8 +30,6 @@ _NODEID_REGEX = re.compile("^(((?P.*)/)?(?P[^/]*?))::(?P.*?)$") -_USE_PLUGIN_V2 = not asbool(os.environ.get("_DD_PYTEST_USE_LEGACY_PLUGIN", "false")) - class _PYTEST_STATUS: ERROR = "error" @@ -197,11 +194,8 @@ def _is_test_unskippable(item: pytest.Item) -> bool: def _extract_span(item): """Extract span from `pytest.Item` instance.""" - if _USE_PLUGIN_V2: - test_id = _get_test_id_from_item(item) - return InternalTest.get_span(test_id) - - return getattr(item, "_datadog_span", None) + test_id = _get_test_id_from_item(item) + return InternalTest.get_span(test_id) def _is_enabled_early(early_config): diff --git a/ddtrace/contrib/internal/pytest/plugin.py b/ddtrace/contrib/internal/pytest/plugin.py index 0908878e0f0..6226df1f35b 100644 --- a/ddtrace/contrib/internal/pytest/plugin.py +++ b/ddtrace/contrib/internal/pytest/plugin.py @@ -17,9 +17,20 @@ import pytest from ddtrace import config -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 +from ddtrace.contrib.internal.pytest._plugin_v2 import is_enabled +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_collection_finish # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_configure as _versioned_pytest_configure +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_module_name # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_suite_name # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_test_name # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_load_initial_conftests # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_report_teststatus # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_runtest_makereport # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_runtest_protocol # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_sessionfinish # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_sessionstart # noqa: F401 +from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_terminal_summary # noqa: F401 from ddtrace.contrib.internal.pytest._utils import _extract_span -from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_itr from ddtrace.settings.asm import config as asm_config @@ -43,11 +54,6 @@ PATCH_ALL_HELP_MSG = "Call ddtrace._patch_all before running tests." -def is_enabled(config): - """Check if the ddtrace plugin is enabled.""" - return (config.getoption("ddtrace") or config.getini("ddtrace")) and not config.getoption("no-ddtrace") - - def pytest_addoption(parser): """Add ddtrace options.""" group = parser.getgroup("ddtrace") @@ -102,37 +108,6 @@ def pytest_addoption(parser): _iast_pytest_activation() -# Version-specific pytest hooks -if _USE_PLUGIN_V2: - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_collection_finish # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_configure as _versioned_pytest_configure - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_module_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_suite_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_ddtrace_get_item_test_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_load_initial_conftests # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_report_teststatus # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_runtest_makereport # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_runtest_protocol # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_sessionfinish # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_sessionstart # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v2 import pytest_terminal_summary # noqa: F401 -else: - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_collection_modifyitems # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_configure as _versioned_pytest_configure - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_ddtrace_get_item_module_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_ddtrace_get_item_suite_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_ddtrace_get_item_test_name # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_load_initial_conftests # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_runtest_makereport # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_runtest_protocol # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_sessionfinish # noqa: F401 - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_sessionstart # noqa: F401 - - # Internal coverage is only used for ITR at the moment, so the hook is only added if the pytest version supports it - if _pytest_version_supports_itr(): - from ddtrace.contrib.internal.pytest._plugin_v1 import pytest_terminal_summary # noqa: F401 - - def pytest_configure(config): config.addinivalue_line("markers", "dd_tags(**kwargs): add tags to current span") if is_enabled(config): diff --git a/ddtrace/contrib/internal/pytest_bdd/__init__.py b/ddtrace/contrib/internal/pytest_bdd/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/ddtrace/contrib/internal/pytest_bdd/_plugin.py b/ddtrace/contrib/internal/pytest_bdd/_plugin.py deleted file mode 100644 index eb7bcc1028a..00000000000 --- a/ddtrace/contrib/internal/pytest_bdd/_plugin.py +++ /dev/null @@ -1,134 +0,0 @@ -import json -import os -import sys - -import pytest - -from ddtrace.contrib.internal.pytest._utils import _extract_span as _extract_feature_span -from ddtrace.contrib.internal.pytest_bdd.constants import FRAMEWORK -from ddtrace.contrib.internal.pytest_bdd.constants import STEP_KIND -from ddtrace.contrib.internal.pytest_bdd.patch import get_version -from ddtrace.ext import test -from ddtrace.internal.ci_visibility import CIVisibility as _CIVisibility -from ddtrace.internal.logger import get_logger - - -log = get_logger(__name__) - - -def _extract_span(item): - """Extract span from `step_func`.""" - return getattr(item, "_datadog_span", None) - - -def _store_span(item, span): - """Store span at `step_func`.""" - item._datadog_span = span - - -def _extract_step_func_args(step, step_func, step_func_args): - """Backwards-compatible get arguments from step_func or step_func_args""" - if not (hasattr(step_func, "parser") or hasattr(step_func, "_pytest_bdd_parsers")): - return step_func_args - - # store parsed step arguments - try: - parsers = [step_func.parser] - except AttributeError: - try: - # pytest-bdd >= 6.0.0 - parsers = step_func._pytest_bdd_parsers - except AttributeError: - parsers = [] - for parser in parsers: - if parser is not None: - converters = getattr(step_func, "converters", {}) - parameters = {} - try: - for arg, value in parser.parse_arguments(step.name).items(): - try: - if arg in converters: - value = converters[arg](value) - except Exception: - log.debug("argument conversion failed.") - parameters[arg] = value - except Exception: - log.debug("argument parsing failed.") - - return parameters or None - - -def _get_step_func_args_json(step, step_func, step_func_args): - """Get step function args as JSON, catching serialization errors""" - try: - extracted_step_func_args = _extract_step_func_args(step, step_func, step_func_args) - if extracted_step_func_args: - return json.dumps(extracted_step_func_args) - return None - except TypeError as err: - log.debug("Could not serialize arguments", exc_info=True) - return json.dumps({"error_serializing_args": str(err)}) - - -class _PytestBddPlugin: - def __init__(self): - self.framework_version = get_version() - - @staticmethod - @pytest.hookimpl(tryfirst=True) - def pytest_bdd_before_scenario(request, feature, scenario): - if _CIVisibility.enabled: - span = _extract_feature_span(request.node) - if span is not None: - location = os.path.relpath(scenario.feature.filename, str(request.config.rootdir)) - span.set_tag(test.NAME, scenario.name) - span.set_tag(test.SUITE, location) # override test suite name with .feature location - - _CIVisibility.set_codeowners_of(location, span=span) - - @pytest.hookimpl(tryfirst=True) - def pytest_bdd_before_step(self, request, feature, scenario, step, step_func): - if _CIVisibility.enabled: - feature_span = _extract_feature_span(request.node) - span = _CIVisibility._instance.tracer.start_span( - step.type, - resource=step.name, - span_type=STEP_KIND, - child_of=feature_span, - activate=True, - ) - span.set_tag_str("component", "pytest_bdd") - - span.set_tag(test.FRAMEWORK, FRAMEWORK) - span.set_tag(test.FRAMEWORK_VERSION, self.framework_version) - - location = os.path.relpath(step_func.__code__.co_filename, str(request.config.rootdir)) - span.set_tag(test.FILE, location) - _CIVisibility.set_codeowners_of(location, span=span) - - _store_span(step_func, span) - - @staticmethod - @pytest.hookimpl(trylast=True) - def pytest_bdd_after_step(request, feature, scenario, step, step_func, step_func_args): - span = _extract_span(step_func) - if span is not None: - step_func_args_json = _get_step_func_args_json(step, step_func, step_func_args) - if step_func_args: - span.set_tag(test.PARAMETERS, step_func_args_json) - span.finish() - - @staticmethod - def pytest_bdd_step_error(request, feature, scenario, step, step_func, step_func_args, exception): - span = _extract_span(step_func) - if span is not None: - if hasattr(exception, "__traceback__"): - tb = exception.__traceback__ - else: - # PY2 compatibility workaround - _, _, tb = sys.exc_info() - step_func_args_json = _get_step_func_args_json(step, step_func, step_func_args) - if step_func_args: - span.set_tag(test.PARAMETERS, step_func_args_json) - span.set_exc_info(type(exception), exception, tb) - span.finish() diff --git a/ddtrace/contrib/internal/pytest_bdd/constants.py b/ddtrace/contrib/internal/pytest_bdd/constants.py deleted file mode 100644 index 2dd377f7619..00000000000 --- a/ddtrace/contrib/internal/pytest_bdd/constants.py +++ /dev/null @@ -1,2 +0,0 @@ -FRAMEWORK = "pytest_bdd" -STEP_KIND = "pytest_bdd.step" diff --git a/ddtrace/contrib/internal/pytest_bdd/patch.py b/ddtrace/contrib/internal/pytest_bdd/patch.py deleted file mode 100644 index efab83aee4b..00000000000 --- a/ddtrace/contrib/internal/pytest_bdd/patch.py +++ /dev/null @@ -1,9 +0,0 @@ -# ddtrace/_monkey.py expects all integrations to define get_version in /patch.py file -def get_version(): - # type: () -> str - try: - import importlib.metadata as importlib_metadata - except ImportError: - import importlib_metadata # type: ignore[no-redef] - - return str(importlib_metadata.version("pytest-bdd")) diff --git a/ddtrace/contrib/internal/pytest_bdd/plugin.py b/ddtrace/contrib/internal/pytest_bdd/plugin.py deleted file mode 100644 index 22856056162..00000000000 --- a/ddtrace/contrib/internal/pytest_bdd/plugin.py +++ /dev/null @@ -1,30 +0,0 @@ -from ddtrace import DDTraceDeprecationWarning -from ddtrace import config -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 -from ddtrace.contrib.internal.pytest.plugin import is_enabled as is_ddtrace_enabled -from ddtrace.vendor.debtcollector import deprecate - - -# pytest-bdd default settings -config._add( - "pytest_bdd", - dict( - _default_service="pytest_bdd", - ), -) - - -def pytest_configure(config): - if config.pluginmanager.hasplugin("pytest-bdd") and config.pluginmanager.hasplugin("ddtrace"): - if not _USE_PLUGIN_V2: - if is_ddtrace_enabled(config): - from ._plugin import _PytestBddPlugin - - deprecate( - "the ddtrace.pytest_bdd plugin is deprecated", - message="it will be integrated with the main pytest ddtrace plugin", - removal_version="3.0.0", - category=DDTraceDeprecationWarning, - ) - - config.pluginmanager.register(_PytestBddPlugin(), "_datadog-pytest-bdd") diff --git a/ddtrace/contrib/internal/pytest_benchmark/_plugin.py b/ddtrace/contrib/internal/pytest_benchmark/_plugin.py deleted file mode 100644 index ee54660afc8..00000000000 --- a/ddtrace/contrib/internal/pytest_benchmark/_plugin.py +++ /dev/null @@ -1,28 +0,0 @@ -import pytest - -from ddtrace.contrib.internal.pytest._utils import _extract_span -from ddtrace.contrib.internal.pytest_benchmark.constants import BENCHMARK_INFO -from ddtrace.contrib.internal.pytest_benchmark.constants import PLUGIN_METRICS -from ddtrace.contrib.internal.pytest_benchmark.constants import PLUGIN_OUTLIERS -from ddtrace.ext.test import TEST_TYPE - - -class _PytestBenchmarkPlugin: - @pytest.hookimpl() - def pytest_runtest_makereport(self, item, call): - fixture = hasattr(item, "funcargs") and item.funcargs.get("benchmark") - if fixture and fixture.stats: - stat_object = fixture.stats.stats - span = _extract_span(item) - - if span is None: - return - - span.set_tag_str(TEST_TYPE, "benchmark") - span.set_tag_str(BENCHMARK_INFO, "Time") - for span_path, tag in PLUGIN_METRICS.items(): - if hasattr(stat_object, tag): - if tag == PLUGIN_OUTLIERS: - span.set_tag_str(span_path, getattr(stat_object, tag)) - continue - span.set_tag(span_path, getattr(stat_object, tag)) diff --git a/ddtrace/contrib/internal/pytest_benchmark/plugin.py b/ddtrace/contrib/internal/pytest_benchmark/plugin.py deleted file mode 100644 index 04728f764a3..00000000000 --- a/ddtrace/contrib/internal/pytest_benchmark/plugin.py +++ /dev/null @@ -1,19 +0,0 @@ -from ddtrace import DDTraceDeprecationWarning -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 -from ddtrace.contrib.internal.pytest.plugin import is_enabled as is_ddtrace_enabled -from ddtrace.vendor.debtcollector import deprecate - - -def pytest_configure(config): - if config.pluginmanager.hasplugin("benchmark") and config.pluginmanager.hasplugin("ddtrace"): - if is_ddtrace_enabled(config): - deprecate( - "this version of the ddtrace.pytest_benchmark plugin is deprecated", - message="it will be integrated with the main pytest ddtrace plugin", - removal_version="3.0.0", - category=DDTraceDeprecationWarning, - ) - if not _USE_PLUGIN_V2: - from ._plugin import _PytestBenchmarkPlugin - - config.pluginmanager.register(_PytestBenchmarkPlugin(), "_datadog-pytest-benchmark") diff --git a/pyproject.toml b/pyproject.toml index 7904657072d..1cfda85d570 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -55,8 +55,6 @@ ddcontextvars_context = "ddtrace.internal.opentelemetry.context:DDRuntimeContext [project.entry-points.pytest11] ddtrace = "ddtrace.contrib.internal.pytest.plugin" -"ddtrace.pytest_bdd" = "ddtrace.contrib.internal.pytest_bdd.plugin" -"ddtrace.pytest_benchmark" = "ddtrace.contrib.internal.pytest_benchmark.plugin" [project.entry-points.'ddtrace.products'] "apm-tracing-rc" = "ddtrace.internal.remoteconfig.products.apm_tracing" diff --git a/riotfile.py b/riotfile.py index b496305fa45..37d73c5a773 100644 --- a/riotfile.py +++ b/riotfile.py @@ -1467,18 +1467,6 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT "pytest": ["~=7.0", latest], "pytest-cov": "==2.12.0", }, - venvs=[ - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "true", - }, - ), - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "false", - }, - ), - ], ), ], ), @@ -1495,18 +1483,6 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT "more_itertools": "<8.11.0", "httpx": latest, }, - venvs=[ - Venv( - env={ - "DD_PYTEST_LEGACY_PLUGIN": "true", - }, - ), - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "false", - }, - ), - ], ), ], ), @@ -1567,18 +1543,6 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT ">=6.0,<6.1", ] }, - venvs=[ - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "true", - }, - ), - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "false", - }, - ), - ], ), Venv( pys=select_pys(min_version="3.10", max_version="3.12"), @@ -1588,18 +1552,6 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT ">=6.0,<6.1", ] }, - venvs=[ - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "true", - }, - ), - Venv( - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "false", - }, - ), - ], ), ], ), @@ -1618,19 +1570,6 @@ def select_pys(min_version: str = MIN_PYTHON_VERSION, max_version: str = MAX_PYT ">=3.1.0,<=4.0.0", ] }, - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "true", - }, - ), - Venv( - pkgs={ - "pytest-benchmark": [ - ">=3.1.0,<=4.0.0", - ] - }, - env={ - "_DD_PYTEST_USE_LEGACY_PLUGIN": "false", - }, ), ], ), diff --git a/tests/ci_visibility/test_cli.py b/tests/ci_visibility/test_cli.py index a34f0f389be..dd1449c73aa 100644 --- a/tests/ci_visibility/test_cli.py +++ b/tests/ci_visibility/test_cli.py @@ -31,8 +31,8 @@ def test_thing(): ], ["pytest", "-p", "no:ddtrace"], ["pytest", "-p", "ddtrace"], - ["pytest", "-p", "ddtrace", "-p", "ddtrace.pytest_bdd", "-p", "ddtrace.pytest_benchmark"], - ["pytest", "-p", "no:ddtrace", "-p", "no:ddtrace.pytest_bdd", "-p", "no:ddtrace.pytest_benchmark"], + ["pytest", "-p", "ddtrace", "-p", "ddtrace.pytest_benchmark"], + ["pytest", "-p", "no:ddtrace", "-p", "no:ddtrace.pytest_benchmark"], ] for command_args in commands_to_test: diff --git a/tests/contrib/flask/test_appsec_flask_pytest_iast_no_snapshot.py b/tests/contrib/flask/test_appsec_flask_pytest_iast_no_snapshot.py index 07f95a55933..823de2d41aa 100644 --- a/tests/contrib/flask/test_appsec_flask_pytest_iast_no_snapshot.py +++ b/tests/contrib/flask/test_appsec_flask_pytest_iast_no_snapshot.py @@ -9,8 +9,7 @@ @pytest.mark.parametrize("iast_enabled", ["true", "false"]) @pytest.mark.parametrize("iast_request_sampling", ["100.0", "0.0"]) -@pytest.mark.parametrize("pytest_use_legacy_plugin", ["false", "true"]) -def test_flask_pytest_iast(iast_enabled, iast_request_sampling, pytest_use_legacy_plugin): +def test_flask_pytest_iast(iast_enabled, iast_request_sampling): from tests.utils import _build_env env = _build_env() @@ -21,7 +20,6 @@ def test_flask_pytest_iast(iast_enabled, iast_request_sampling, pytest_use_legac "DD_TRACE_SQLITE_ENABLED": "0", "DD_IAST_ENABLED": iast_enabled, "DD_TRACE_DEBUG": "true", - "_DD_PYTEST_USE_LEGACY_PLUGIN": pytest_use_legacy_plugin, "DD_IAST_REQUEST_SAMPLING": iast_request_sampling, # "DD_API_KEY": "invalidapikey", # "DD_CIVISIBILITY_AGENTLESS_ENABLED": "1", diff --git a/tests/contrib/pytest/test_coverage_per_suite.py b/tests/contrib/pytest/test_coverage_per_suite.py index 6527f56803b..fb7e950276d 100644 --- a/tests/contrib/pytest/test_coverage_per_suite.py +++ b/tests/contrib/pytest/test_coverage_per_suite.py @@ -1,10 +1,8 @@ -import json import os from unittest import mock import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_itr from ddtrace.ext.test_visibility import ITR_SKIPPING_LEVEL from ddtrace.internal.ci_visibility._api_client import ITRData @@ -32,21 +30,11 @@ def _get_tuples_from_segments(segments): return list((segment[0], segment[2]) for segment in segments) -def _get_span_coverage_data(span, use_plugin_v2=False): +def _get_span_coverage_data(span): """Returns an abstracted view of the coverage data from the span that is independent of the coverage format.""" - if use_plugin_v2: - tag_data = span.get_struct_tag(COVERAGE_TAG_NAME) - assert tag_data is not None, f"Coverage data not found in span {span}" - return { - file_data["filename"]: _get_tuples_from_bytearray(file_data["bitmap"]) for file_data in tag_data["files"] - } - - else: - # This will raise an exception and the test will fail if the tag is not found - tag_data = json.loads(span.get_tag(COVERAGE_TAG_NAME)) - return { - file_data["filename"]: _get_tuples_from_segments(file_data["segments"]) for file_data in tag_data["files"] - } + tag_data = span.get_struct_tag(COVERAGE_TAG_NAME) + assert tag_data is not None, f"Coverage data not found in span {span}" + return {file_data["filename"]: _get_tuples_from_bytearray(file_data["bitmap"]) for file_data in tag_data["files"]} class PytestTestCase(PytestTestCaseBase): @@ -139,40 +127,30 @@ def test_second(): test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] first_suite_span = test_suite_spans[0] assert first_suite_span.get_tag("type") == "test_suite_end" - first_suite_coverage = _get_span_coverage_data(first_suite_span, _USE_PLUGIN_V2) + first_suite_coverage = _get_span_coverage_data(first_suite_span) assert len(first_suite_coverage) == 3 - if _USE_PLUGIN_V2: - assert first_suite_coverage["/test_cov.py"] == [ - (1, 2), - (4, 5), - (7, 9), - (11, 13), - (16, 17), - (20, 22), - (24, 25), - (28, 31), - (33, 36), - (39, 42), - (44, 45), - ] - assert first_suite_coverage["/lib_fn.py"] == [(1, 2)] - assert first_suite_coverage["/ret_false.py"] == [(1, 2)] - - else: - assert first_suite_coverage["test_cov.py"] == [(5, 5), (8, 9), (12, 13), (21, 22), (35, 36)] - assert first_suite_coverage["lib_fn.py"] == [(2, 2)] - assert first_suite_coverage["ret_false.py"] == [(1, 2)] + assert first_suite_coverage["/test_cov.py"] == [ + (1, 2), + (4, 5), + (7, 9), + (11, 13), + (16, 17), + (20, 22), + (24, 25), + (28, 31), + (33, 36), + (39, 42), + (44, 45), + ] + assert first_suite_coverage["/lib_fn.py"] == [(1, 2)] + assert first_suite_coverage["/ret_false.py"] == [(1, 2)] second_suite_span = test_suite_spans[-1] assert second_suite_span.get_tag("type") == "test_suite_end" - second_suite_coverage = _get_span_coverage_data(second_suite_span, _USE_PLUGIN_V2) + second_suite_coverage = _get_span_coverage_data(second_suite_span) assert len(second_suite_coverage) == 2 - if _USE_PLUGIN_V2: - assert second_suite_coverage["/test_cov_second.py"] == [(1, 1), (3, 5)] - assert second_suite_coverage["/ret_false.py"] == [(1, 2)] - else: - assert second_suite_coverage["test_cov_second.py"] == [(4, 5)] - assert second_suite_coverage["ret_false.py"] == [(2, 2)] + assert second_suite_coverage["/test_cov_second.py"] == [(1, 1), (3, 5)] + assert second_suite_coverage["/ret_false.py"] == [(1, 2)] def test_pytest_will_report_coverage_by_suite_with_itr_skipped(self): self.testdir.makepyfile( @@ -249,17 +227,10 @@ def test_second(): second_suite_span = test_suite_spans[1] assert second_suite_span.get_tag("type") == "test_suite_end" - first_suite_coverage = _get_span_coverage_data(first_suite_span, _USE_PLUGIN_V2) - - if _USE_PLUGIN_V2: - assert len(first_suite_coverage) == 3 - assert first_suite_coverage["/test_cov.py"] == [(1, 2), (4, 5), (7, 9)] - assert first_suite_coverage["/lib_fn.py"] == [(1, 2)] - assert first_suite_coverage["/ret_false.py"] == [(1, 2)] - assert second_suite_span.get_struct_tag(COVERAGE_TAG_NAME) is None - else: - assert len(first_suite_coverage) == 3 - assert first_suite_coverage["test_cov.py"] == [(5, 5), (8, 9)] - assert first_suite_coverage["lib_fn.py"] == [(2, 2)] - assert first_suite_coverage["ret_false.py"] == [(1, 2)] - assert COVERAGE_TAG_NAME not in second_suite_span.get_tags() + first_suite_coverage = _get_span_coverage_data(first_suite_span) + + assert len(first_suite_coverage) == 3 + assert first_suite_coverage["/test_cov.py"] == [(1, 2), (4, 5), (7, 9)] + assert first_suite_coverage["/lib_fn.py"] == [(1, 2)] + assert first_suite_coverage["/ret_false.py"] == [(1, 2)] + assert second_suite_span.get_struct_tag(COVERAGE_TAG_NAME) is None diff --git a/tests/contrib/pytest/test_pytest.py b/tests/contrib/pytest/test_pytest.py index 838078fdde9..5c885e1d4a5 100644 --- a/tests/contrib/pytest/test_pytest.py +++ b/tests/contrib/pytest/test_pytest.py @@ -9,7 +9,6 @@ import ddtrace from ddtrace.constants import _SAMPLING_PRIORITY_KEY from ddtrace.constants import ERROR_MSG -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest.constants import XFAIL_REASON from ddtrace.contrib.internal.pytest.patch import get_version from ddtrace.contrib.internal.pytest.plugin import is_enabled @@ -20,7 +19,6 @@ from ddtrace.internal.ci_visibility import CIVisibility from ddtrace.internal.ci_visibility._api_client import ITRData from ddtrace.internal.ci_visibility._api_client import TestVisibilityAPISettings -from ddtrace.internal.ci_visibility.constants import COVERAGE_TAG_NAME from ddtrace.internal.ci_visibility.constants import ITR_CORRELATION_ID_TAG_NAME from ddtrace.internal.ci_visibility.encoder import CIVisibilityEncoderV01 from tests.ci_visibility.api_client._util import _make_fqdn_suite_ids @@ -397,35 +395,6 @@ def test_1(self, item): "metadata": {}, } - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_skip(self): - """Test skip case.""" - py_file = self.testdir.makepyfile( - """ - import pytest - - @pytest.mark.skip(reason="decorator") - def test_decorator(): - pass - - def test_body(): - pytest.skip("body") - """ - ) - file_name = os.path.basename(py_file.strpath) - rec = self.inline_run("--ddtrace", file_name) - rec.assertoutcome(skipped=2) - spans = self.pop_spans() - - assert len(spans) == 5 - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert test_spans[0].get_tag(test.STATUS) == test.Status.SKIP.value - assert test_spans[0].get_tag(test.SKIP_REASON) == "decorator" - assert test_spans[1].get_tag(test.STATUS) == test.Status.SKIP.value - assert test_spans[1].get_tag(test.SKIP_REASON) == "body" - assert test_spans[0].get_tag("component") == "pytest" - assert test_spans[1].get_tag("component") == "pytest" - def test_skip_module_with_xfail_cases(self): """Test Xfail test cases for a module that is skipped entirely, which should be treated as skip tests.""" py_file = self.testdir.makepyfile( @@ -781,7 +750,7 @@ def test_foo(): rec.assertoutcome(passed=3) spans = self.pop_spans() - assert len(spans) == (6 if _USE_PLUGIN_V2 else 8) + assert len(spans) == 6 non_session_spans = [span for span in spans if span.get_tag("type") != "test_session_end"] for span in non_session_spans: if span.get_tag("type") == "test_suite_end": @@ -948,7 +917,7 @@ def test_team_b(): self.inline_run("--ddtrace", *file_names) spans = self.pop_spans() - assert len(spans) == (6 if _USE_PLUGIN_V2 else 7) + assert len(spans) == 6 test_spans = [span for span in spans if span.get_tag("type") == "test"] assert json.loads(test_spans[0].get_tag(test.CODEOWNERS)) == ["@default-team"], test_spans[0] assert json.loads(test_spans[1].get_tag(test.CODEOWNERS)) == ["@team-b", "@backup-b"], test_spans[1] @@ -981,25 +950,6 @@ def test_pytest_session(self): assert spans[0].get_tag("test_session_id") == str(spans[0].span_id) assert spans[0].get_tag("test.command") == "pytest -p no:randomly --ddtrace" - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not use class hierarchy") - def test_pytest_test_class_hierarchy_is_added_to_test_span(self): - """Test that given a test class, the test span will include the hierarchy of test class(es) as a tag.""" - py_file = self.testdir.makepyfile( - """ - class TestNestedOuter: - class TestNestedInner: - def test_ok(self): - assert True - """ - ) - file_name = os.path.basename(py_file.strpath) - rec = self.inline_run("--ddtrace", file_name) - rec.assertoutcome(passed=1) - spans = self.pop_spans() - assert len(spans) == 4 - test_span = spans[0] - assert test_span.get_tag("test.class_hierarchy") == "TestNestedOuter.TestNestedInner" - def test_pytest_suite(self): """Test that running pytest on a test file will generate a test suite span.""" py_file = self.testdir.makepyfile( @@ -1050,7 +1000,7 @@ def test_not_ok(): self.inline_run("--ddtrace") spans = self.pop_spans() - assert len(spans) == (6 if _USE_PLUGIN_V2 else 7) + assert len(spans) == 6 test_session_span = _get_spans_from_list(spans, "session")[0] assert test_session_span.name == "pytest.test_session" assert test_session_span.parent_id is None @@ -1089,8 +1039,6 @@ def test_outside_class_after(): test_span_a_outside_after_class = spans[2] test_suite_a_span = spans[5] assert test_suite_a_span.get_tag("type") == "test_suite_end" - if not _USE_PLUGIN_V2: - assert test_span_a_inside_class.get_tag("test.class_hierarchy") == "TestClass" assert test_suite_a_span.start_ns + test_suite_a_span.duration_ns >= test_span_a_outside_after_class.start_ns def test_pytest_suites_one_fails_propagates(self): @@ -1118,14 +1066,14 @@ def test_not_ok(): assert test_a_module_span.get_tag("type") == "test_module_end" test_a_suite_span = _get_spans_from_list(spans, "suite", "test_a.py")[0] assert test_a_suite_span.get_tag("type") == "test_suite_end" - test_b_module_span = test_module_spans[0] if _USE_PLUGIN_V2 else test_module_spans[1] + test_b_module_span = test_module_spans[0] assert test_b_module_span.get_tag("type") == "test_module_end" test_b_suite_span = _get_spans_from_list(spans, "suite", "test_b.py")[0] assert test_b_suite_span.get_tag("type") == "test_suite_end" assert test_session_span.get_tag("test.status") == "fail" assert test_a_suite_span.get_tag("test.status") == "pass" assert test_b_suite_span.get_tag("test.status") == "fail" - assert test_a_module_span.get_tag("test.status") == ("fail" if _USE_PLUGIN_V2 else "pass") + assert test_a_module_span.get_tag("test.status") == "fail" assert test_b_module_span.get_tag("test.status") == "fail" def test_pytest_suites_one_skip_does_not_propagate(self): @@ -1155,7 +1103,7 @@ def test_not_ok(): assert test_a_module_span.get_tag("type") == "test_module_end" test_a_suite_span = _get_spans_from_list(spans, "suite", "test_a.py")[0] assert test_a_suite_span.get_tag("type") == "test_suite_end" - test_b_module_span = test_module_spans[0] if _USE_PLUGIN_V2 else test_module_spans[1] + test_b_module_span = test_module_spans[0] assert test_b_module_span.get_tag("type") == "test_module_end" test_b_suite_span = _get_spans_from_list(spans, "suite", "test_b.py")[0] assert test_b_suite_span.get_tag("type") == "test_suite_end" @@ -1163,7 +1111,7 @@ def test_not_ok(): assert test_a_suite_span.get_tag("test.status") == "pass" assert test_b_suite_span.get_tag("test.status") == "skip" assert test_a_module_span.get_tag("test.status") == "pass" - assert test_b_module_span.get_tag("test.status") == ("pass" if _USE_PLUGIN_V2 else "skip") + assert test_b_module_span.get_tag("test.status") == "pass" def test_pytest_all_tests_pass_status_propagates(self): """Test that if all tests pass, the status propagates upwards.""" @@ -1601,309 +1549,6 @@ def test_cov(): assert len(test_suite_spans) == 1 assert test_suite_spans[0].get_tag("test.suite") == "test_cov.py" - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_will_report_coverage_by_test(self): - self.testdir.makepyfile( - ret_false=""" - def ret_false(): - return False - """ - ) - self.testdir.makepyfile( - lib_fn=""" - def lib_fn(): - return True - """ - ) - py_cov_file = self.testdir.makepyfile( - test_cov=""" - import pytest - - def test_cov(): - from lib_fn import lib_fn - assert lib_fn() - - def test_second(): - from ret_false import ret_false - assert not ret_false() - """ - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._check_enabled_features", - return_value=TestVisibilityAPISettings(True, False, False, True), - ): - self.inline_run("--ddtrace", os.path.basename(py_cov_file.strpath)) - spans = self.pop_spans() - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - assert session_span.get_tag("test.code_coverage.enabled") == "true" - - first_test_span = spans[0] - assert first_test_span.get_tag("test.name") == "test_cov" - assert first_test_span.get_tag("type") == "test" - assert COVERAGE_TAG_NAME in first_test_span.get_tags() - first_tag_data = json.loads(first_test_span.get_tag(COVERAGE_TAG_NAME)) - files = sorted(first_tag_data["files"], key=lambda x: x["filename"]) - assert len(files) == 2 - assert files[0]["filename"] == "lib_fn.py" - assert files[1]["filename"] == "test_cov.py" - assert len(files[0]["segments"]) == 1 - assert files[0]["segments"][0] == [1, 0, 2, 0, -1] - assert len(files[1]["segments"]) == 1 - assert files[1]["segments"][0] == [4, 0, 5, 0, -1] - - second_test_span = spans[1] - assert second_test_span.get_tag("type") == "test" - assert second_test_span.get_tag("test.name") == "test_second" - assert COVERAGE_TAG_NAME in second_test_span.get_tags() - second_tag_data = json.loads(second_test_span.get_tag(COVERAGE_TAG_NAME)) - files = sorted(second_tag_data["files"], key=lambda x: x["filename"]) - assert len(files) == 2 - assert files[0]["filename"] == "ret_false.py" - assert files[1]["filename"] == "test_cov.py" - assert len(files[0]["segments"]) == 1 - assert files[0]["segments"][0] == [1, 0, 2, 0, -1] - assert len(files[1]["segments"]) == 1 - assert files[1]["segments"][0] == [8, 0, 9, 0, -1] - - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_will_report_coverage_by_test_with_itr_skipped(self): - self.testdir.makepyfile( - test_ret_false=""" - def ret_false(): - return False - """ - ) - self.testdir.makepyfile( - test_module=""" - def lib_fn(): - return True - """ - ) - py_cov_file = self.testdir.makepyfile( - test_cov=""" - import pytest - - def test_cov(): - from test_module import lib_fn - assert lib_fn() - - def test_second(): - from test_ret_false import ret_false - assert not ret_false() - """ - ) - - _itr_data = ITRData( - skippable_items=_make_fqdn_test_ids( - [ - ("", "test_cov.py", "test_cov"), - ] - ) - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._check_enabled_features", - return_value=TestVisibilityAPISettings(True, True, False, True), - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ): - self.inline_run("--ddtrace", os.path.basename(py_cov_file.strpath)) - spans = self.pop_spans() - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.code_coverage.enabled") == "true" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.tests_skipping.type") == "test" - assert session_span.get_metric("test.itr.tests_skipping.count") == 1 - - first_test_span = spans[0] - assert first_test_span.get_tag("test.name") == "test_cov" - assert first_test_span.get_tag("type") == "test" - assert COVERAGE_TAG_NAME not in first_test_span.get_tags() - - second_test_span = spans[1] - assert second_test_span.get_tag("type") == "test" - assert second_test_span.get_tag("test.name") == "test_second" - assert COVERAGE_TAG_NAME in second_test_span.get_tags() - second_tag_data = json.loads(second_test_span.get_tag(COVERAGE_TAG_NAME)) - files = sorted(second_tag_data["files"], key=lambda x: x["filename"]) - assert len(files) == 2 - assert files[0]["filename"] == "test_cov.py" - assert files[1]["filename"] == "test_ret_false.py" - assert len(files[0]["segments"]) == 1 - assert files[0]["segments"][0] == [8, 0, 9, 0, -1] - assert len(files[1]["segments"]) == 1 - assert files[1]["segments"][0] == [1, 0, 2, 0, -1] - - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_will_report_coverage_by_test_with_pytest_mark_skip(self): - self.testdir.makepyfile( - test_ret_false=""" - def ret_false(): - return False - """ - ) - self.testdir.makepyfile( - test_module=""" - def lib_fn(): - return True - """ - ) - py_cov_file = self.testdir.makepyfile( - test_cov=""" - import pytest - - @pytest.mark.skip - def test_cov(): - from test_module import lib_fn - assert lib_fn() - - def test_second(): - from test_ret_false import ret_false - assert not ret_false() - - def skipif_false_check(): - return False - skipif_false_decorator = pytest.mark.skipif( - skipif_false_check(), reason="skip if False" - ) - @skipif_false_decorator - def test_skipif_mark_false(): - from test_ret_false import ret_false - assert ret_false() is False - - def skipif_true_check(): - return True - skipif_true_decorator = pytest.mark.skipif( - skipif_true_check(), reason="skip is True" - ) - @skipif_true_decorator - def test_skipif_mark_true(): - assert True is False - """ - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._check_enabled_features", - return_value=TestVisibilityAPISettings(True, False, False, True), - ): - self.inline_run("--ddtrace", os.path.basename(py_cov_file.strpath)) - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - assert session_span.get_tag("test.code_coverage.enabled") == "true" - - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert len(test_spans) == 4 - - first_test_span = spans[0] - assert first_test_span.get_tag("test.name") == "test_cov" - assert COVERAGE_TAG_NAME not in first_test_span.get_tags() - - second_test_span = spans[1] - assert second_test_span.get_tag("test.name") == "test_second" - assert COVERAGE_TAG_NAME in second_test_span.get_tags() - second_tag_data = json.loads(second_test_span.get_tag(COVERAGE_TAG_NAME)) - second_test_files = sorted(second_tag_data["files"], key=lambda x: x["filename"]) - assert len(second_test_files) == 2 - assert second_test_files[0]["filename"] == "test_cov.py" - assert len(second_test_files[0]["segments"]) == 1 - assert second_test_files[0]["segments"][0] == [9, 0, 10, 0, -1] - assert second_test_files[1]["filename"] == "test_ret_false.py" - assert len(second_test_files[1]["segments"]) == 1 - assert second_test_files[1]["segments"][0] == [1, 0, 2, 0, -1] - - third_test_span = spans[2] - assert third_test_span.get_tag("test.name") == "test_skipif_mark_false" - assert COVERAGE_TAG_NAME in third_test_span.get_tags() - third_tag_data = json.loads(third_test_span.get_tag(COVERAGE_TAG_NAME)) - third_test_files = sorted(third_tag_data["files"], key=lambda x: x["filename"]) - assert len(third_test_files) == 2 - assert third_test_files[0]["filename"] == "test_cov.py" - assert len(third_test_files[0]["segments"]) == 1 - assert third_test_files[0]["segments"][0] == [19, 0, 20, 0, -1] - - fourth_test_span = spans[3] - assert fourth_test_span.get_tag("test.name") == "test_skipif_mark_true" - assert COVERAGE_TAG_NAME not in fourth_test_span.get_tags() - - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_will_report_coverage_by_test_with_pytest_skip(self): - self.testdir.makepyfile( - test_ret_false=""" - def ret_false(): - return False - """ - ) - self.testdir.makepyfile( - test_module=""" - def lib_fn(): - return True - """ - ) - py_cov_file = self.testdir.makepyfile( - test_cov=""" - import pytest - - def test_cov(): - two = 1 + 1 - pytest.skip() - from test_module import lib_fn - assert lib_fn() - - def test_second(): - from test_ret_false import ret_false - assert not ret_false() - """ - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._check_enabled_features", - return_value=TestVisibilityAPISettings(True, False, False, True), - ): - self.inline_run("--ddtrace", os.path.basename(py_cov_file.strpath)) - spans = self.pop_spans() - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - assert session_span.get_tag("test.code_coverage.enabled") == "true" - - module_span = [span for span in spans if span.get_tag("type") == "test_module_end"][0] - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - assert module_span.get_tag("test.code_coverage.enabled") == "true" - - first_test_span = spans[0] - assert first_test_span.get_tag("test.name") == "test_cov" - assert first_test_span.get_tag("type") == "test" - assert COVERAGE_TAG_NAME in first_test_span.get_tags() - first_tag_data = json.loads(first_test_span.get_tag(COVERAGE_TAG_NAME)) - files = sorted(first_tag_data["files"], key=lambda x: x["filename"]) - assert len(files) == 1 - assert files[0]["filename"] == "test_cov.py" - assert len(files[0]["segments"]) == 1 - assert files[0]["segments"][0] == [4, 0, 5, 0, -1] - - second_test_span = spans[1] - assert second_test_span.get_tag("type") == "test" - assert second_test_span.get_tag("test.name") == "test_second" - assert COVERAGE_TAG_NAME in second_test_span.get_tags() - second_tag_data = json.loads(second_test_span.get_tag(COVERAGE_TAG_NAME)) - files = sorted(second_tag_data["files"], key=lambda x: x["filename"]) - assert len(files) == 2 - assert files[0]["filename"] == "test_cov.py" - assert files[1]["filename"] == "test_ret_false.py" - assert len(files[0]["segments"]) == 1 - assert files[0]["segments"][0] == [10, 0, 11, 0, -1] - assert len(files[1]["segments"]) == 1 - assert files[1]["segments"][0] == [1, 0, 2, 0, -1] - def test_pytest_will_report_git_metadata(self): py_file = self.testdir.makepyfile( """ @@ -2064,13 +1709,11 @@ def test_inner_class_ok(self): assert skipped_test_span.get_tag("test.skipped_by_itr") == "true" assert skipped_test_span.get_tag("itr_correlation_id") is None - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_skip_tests_by_path(self): + def test_pytest_skip_all_test_suites(self): """ Test that running pytest on two nested packages with 1 test each. It should generate 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, but - the outer suite is skipped with ITR, so only 1 test suite span is created, - 1 test module and 1 test span, hence 4 spans. + all test suites are skipped with ITR. All the spans and tags are reported accordingly. """ package_outer_dir = self.testdir.mkpydir("test_outer_package") os.chdir(str(package_outer_dir)) @@ -2089,75 +1732,63 @@ def test_pytest_skip_tests_by_path(self): assert True""" ) self.testdir.chdir() - - _itr_data = ITRData( - skippable_items=_make_fqdn_test_ids( - [ - ("test_outer_package", "test_outer_abc.py", "test_outer_ok"), - ] - ) - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ), mock.patch( + with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", return_value=True, + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", + return_value=True, + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip" + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=True + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_item_itr_skippable", return_value=True + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.ddconfig", + _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), ): self.inline_run("--ddtrace") spans = self.pop_spans() assert len(spans) == 7 - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.status") == "pass" + session_span = _get_spans_from_list(spans, "session")[0] assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.tests_skipping.type") == "test" - assert session_span.get_metric("test.itr.tests_skipping.count") == 1 - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - outer_module_span = [span for span in module_spans if span.get_tag("test.module") == "test_outer_package"][0] - assert outer_module_span.get_tag("test.status") == "skip" - assert outer_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert outer_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert outer_module_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert outer_module_span.get_tag("test.itr.tests_skipping.type") == "test" - assert outer_module_span.get_metric("test.itr.tests_skipping.count") == 1 + assert session_span.get_tag("test.itr.tests_skipping.type") == "suite" + assert session_span.get_metric("test.itr.tests_skipping.count") == 2 - inner_module_span = [ - span for span in module_spans if span.get_tag("test.module") == "test_outer_package.test_inner_package" - ][0] - assert inner_module_span.get_tag("test.status") == "pass" - assert inner_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert inner_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert inner_module_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert inner_module_span.get_tag("test.itr.tests_skipping.type") == "test" - assert inner_module_span.get_metric("test.itr.tests_skipping.count") == 0 + module_spans = _get_spans_from_list(spans, "module") + for module_span in module_spans: + assert module_span.get_metric("test.itr.tests_skipping.count") == 1 + assert module_span.get_tag("test.itr.tests_skipping.type") == "suite" + assert module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" + assert module_span.get_tag("test.itr.tests_skipping.enabled") == "true" passed_spans = [x for x in spans if x.get_tag("test.status") == "pass"] - assert len(passed_spans) == 4 + assert len(passed_spans) == 0 skipped_spans = [x for x in spans if x.get_tag("test.status") == "skip"] - assert len(skipped_spans) == 3 + assert len(skipped_spans) == 7 - suite_spans = [x for x in spans if x.get_tag("type") == "test_suite_end"] - for suite_span in suite_spans: - assert suite_span.get_tag("itr_correlation_id") is None + skipped_suite_spans = [ + x for x in spans if x.get_tag("test.status") == "skip" and x.get_tag("type") == "test_suite_end" + ] + assert len(skipped_suite_spans) == 2 + for skipped_suite_span in skipped_suite_spans: + assert skipped_suite_span.get_tag("test.skipped_by_itr") == "true" - skipped_test_spans = [x for x in skipped_spans if x.get_tag("type") == "test"] + skipped_test_spans = [x for x in spans if x.get_tag("test.status") == "skip" and x.get_tag("type") == "test"] + assert len(skipped_test_spans) == 2 for skipped_test_span in skipped_test_spans: assert skipped_test_span.get_tag("test.skipped_by_itr") == "true" - assert skipped_test_span.get_tag("itr_correlation_id") == "pytestitrcorrelationid" - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_skip_none_tests(self): + def test_pytest_skip_none_test_suites(self): """ Test that running pytest on two nested packages with 1 test each. It should generate 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, and - no tests are skipped with ITR. All the spans and tags are reported accordingly. + no test suites are skipped with ITR. All the spans and tags are reported accordingly. """ package_outer_dir = self.testdir.mkpydir("test_outer_package") os.chdir(str(package_outer_dir)) @@ -2176,11 +1807,19 @@ def test_pytest_skip_none_tests(self): assert True""" ) self.testdir.chdir() - with mock.patch( + with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", return_value=True, - ), mock.patch("ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip"), mock.patch( + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", + return_value=True, + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip" + ), mock.patch( "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=False + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.ddconfig", + _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), ): self.inline_run("--ddtrace") @@ -2191,13 +1830,13 @@ def test_pytest_skip_none_tests(self): assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert session_span.get_tag("test.itr.tests_skipping.type") == "test" + assert session_span.get_tag("test.itr.tests_skipping.type") == "suite" assert session_span.get_metric("test.itr.tests_skipping.count") == 0 module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] for module_span in module_spans: assert module_span.get_metric("test.itr.tests_skipping.count") == 0 - assert module_span.get_tag("test.itr.tests_skipping.type") == "test" + assert module_span.get_tag("test.itr.tests_skipping.type") == "suite" assert module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" assert module_span.get_tag("test.itr.tests_skipping.enabled") == "true" @@ -2206,12 +1845,11 @@ def test_pytest_skip_none_tests(self): skipped_spans = [x for x in spans if x.get_tag("test.status") == "skip"] assert len(skipped_spans) == 0 - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_skip_all_tests(self): + def test_pytest_skip_suite_by_path_but_test_skipping_not_enabled(self): """ Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, but - all tests are skipped with ITR. All the spans and tags are reported accordingly. + 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, + both suites are to be skipped with ITR, but test skipping is disabled. """ package_outer_dir = self.testdir.mkpydir("test_outer_package") os.chdir(str(package_outer_dir)) @@ -2230,565 +1868,22 @@ def test_pytest_skip_all_tests(self): assert True""" ) self.testdir.chdir() - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", - return_value=True, - ), mock.patch("ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip"), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=True - ): - self.inline_run("--ddtrace") - spans = self.pop_spans() - assert len(spans) == 7 + _itr_data = ITRData( + skippable_items=_make_fqdn_suite_ids( + [ + ("test_outer_package.test_inner_package", "test_inner_abc.py"), + ("test_outer_package", "test_outer_abc.py"), + ] + ) + ) - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.tests_skipping.type") == "test" - assert session_span.get_metric("test.itr.tests_skipping.count") == 2 - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - for module_span in module_spans: - assert module_span.get_metric("test.itr.tests_skipping.count") == 1 - assert module_span.get_tag("test.itr.tests_skipping.type") == "test" - assert module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - - passed_spans = [x for x in spans if x.get_tag("test.status") == "pass"] - assert len(passed_spans) == 0 - skipped_spans = [x for x in spans if x.get_tag("test.status") == "skip"] - assert len(skipped_spans) == 7 - - skipped_test_spans = [x for x in skipped_spans if x.get_tag("type") == "test"] - assert len(skipped_test_spans) == 2 - for skipped_test_span in skipped_test_spans: - assert skipped_test_span.get_tag("test.skipped_by_itr") == "true" - - def test_pytest_skip_all_test_suites(self): - """ - Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, but - all test suites are skipped with ITR. All the spans and tags are reported accordingly. - """ - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - """def test_outer_ok(): - assert True""" - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - """def test_inner_ok(): - assert True""" - ) - self.testdir.chdir() - with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", - return_value=True, - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", - return_value=True, - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip" - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=True - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_item_itr_skippable", return_value=True - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.ddconfig", - _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = _get_spans_from_list(spans, "session")[0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.tests_skipping.type") == "suite" - assert session_span.get_metric("test.itr.tests_skipping.count") == 2 - - module_spans = _get_spans_from_list(spans, "module") - for module_span in module_spans: - assert module_span.get_metric("test.itr.tests_skipping.count") == 1 - assert module_span.get_tag("test.itr.tests_skipping.type") == "suite" - assert module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - - passed_spans = [x for x in spans if x.get_tag("test.status") == "pass"] - assert len(passed_spans) == 0 - skipped_spans = [x for x in spans if x.get_tag("test.status") == "skip"] - assert len(skipped_spans) == 7 - - skipped_suite_spans = [ - x for x in spans if x.get_tag("test.status") == "skip" and x.get_tag("type") == "test_suite_end" - ] - assert len(skipped_suite_spans) == 2 - for skipped_suite_span in skipped_suite_spans: - assert skipped_suite_span.get_tag("test.skipped_by_itr") == "true" - - skipped_test_spans = [x for x in spans if x.get_tag("test.status") == "skip" and x.get_tag("type") == "test"] - assert len(skipped_test_spans) == 2 - for skipped_test_span in skipped_test_spans: - assert skipped_test_span.get_tag("test.skipped_by_itr") == "true" - - def test_pytest_skip_none_test_suites(self): - """ - Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, and - no test suites are skipped with ITR. All the spans and tags are reported accordingly. - """ - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - """def test_outer_ok(): - assert True""" - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - """def test_inner_ok(): - assert True""" - ) - self.testdir.chdir() - with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", - return_value=True, - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", - return_value=True, - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip" - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=False - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.ddconfig", - _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert session_span.get_tag("test.itr.tests_skipping.type") == "suite" - assert session_span.get_metric("test.itr.tests_skipping.count") == 0 - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - for module_span in module_spans: - assert module_span.get_metric("test.itr.tests_skipping.count") == 0 - assert module_span.get_tag("test.itr.tests_skipping.type") == "suite" - assert module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - - passed_spans = [x for x in spans if x.get_tag("test.status") == "pass"] - assert len(passed_spans) == 7 - skipped_spans = [x for x in spans if x.get_tag("test.status") == "skip"] - assert len(skipped_spans) == 0 - - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_skip_all_tests_but_test_skipping_not_enabled(self): - """ - Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans. - All test suites match to be skipped with ITR, but test skipping is not enabled. - """ - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - """def test_outer_ok(): - assert True""" - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - """def test_inner_ok(): - assert True""" - ) - self.testdir.chdir() - with mock.patch("ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip"), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._should_skip_path", return_value=True - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - for module_span in module_spans: - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] - assert len(test_suite_spans) == 2 - - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert len(test_spans) == 2 - passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] - assert len(passed_test_spans) == 2 - - def test_pytest_skip_suite_by_path_but_test_skipping_not_enabled(self): - """ - Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, - both suites are to be skipped with ITR, but test skipping is disabled. - """ - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - """def test_outer_ok(): - assert True""" - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - """def test_inner_ok(): - assert True""" - ) - self.testdir.chdir() - - _itr_data = ITRData( - skippable_items=_make_fqdn_suite_ids( - [ - ("test_outer_package.test_inner_package", "test_inner_abc.py"), - ("test_outer_package", "test_outer_abc.py"), - ] - ) - ) - - with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", - return_value=True, - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.ddconfig", - _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - for module_span in module_spans: - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] - assert len(test_suite_spans) == 2 - - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert len(test_spans) == 2 - passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] - assert len(passed_test_spans) == 2 - - def test_pytest_skip_tests_by_path_but_test_skipping_not_enabled(self): - """ - Test that running pytest on two nested packages with 1 test each. It should generate - 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, - both suites are to be skipped with ITR, but test skipping is disabled. - """ - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - """def test_outer_ok(): - assert True""" - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - """def test_inner_ok(): - assert True""" - ) - self.testdir.chdir() - - _itr_data = ITRData( - skippable_items=_make_fqdn_test_ids( - [ - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_ok"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skipif"), - ("test_outer_package", "test_outer_abc.py", "test_outer_ok"), - ] - ) - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", - return_value=True, - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 7 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - for module_span in module_spans: - assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - - test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] - assert len(test_suite_spans) == 2 - - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert len(test_spans) == 2 - passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] - assert len(passed_test_spans) == 2 - - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_unskippable_tests_forced_run_in_test_level(self): - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - textwrap.dedent( - ( - """ - def test_outer_ok(): - assert True - """ - ) - ) - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - textwrap.dedent( - """ - import pytest - def test_inner_ok(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_unskippable(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(True, reason="skipped anyway") - def test_inner_shouldskip_skipif(): - assert False - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skip(reason="just skip it") - def test_inner_shouldskip_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_itr_wont_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(False, reason="was not going to skip anyway") - def test_inner_wasnot_going_to_skip_skipif(): - assert True - """ - ) - ) - self.testdir.chdir() - - _itr_data = ITRData( - skippable_items=_make_fqdn_test_ids( - [ - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_ok"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_unskippable"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skipif"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skip"), - ("test_outer_package", "test_outer_abc.py", "test_outer_ok"), - ] - ) - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", - return_value=True, - ): - self.inline_run("--ddtrace") - - spans = self.pop_spans() - assert len(spans) == 12 - - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.unskippable") == "true" - assert session_span.get_tag("test.itr.forced_run") == "true" - - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] - assert len(module_spans) == 2 - - outer_module_span = [span for span in module_spans if span.get_tag("test.module") == "test_outer_package"][0] - assert outer_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert outer_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert outer_module_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert outer_module_span.get_tag("test.itr.forced_run") == "false" - - inner_module_span = [ - span for span in module_spans if span.get_tag("test.module") == "test_outer_package.test_inner_package" - ][0] - assert inner_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert inner_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert inner_module_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert inner_module_span.get_tag("test.itr.forced_run") == "true" - - test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] - assert len(test_suite_spans) == 2 - - inner_suite_span = [span for span in test_suite_spans if span.get_tag("test.suite") == "test_inner_abc.py"][0] - assert inner_suite_span.get_tag("test.itr.forced_run") == "true" - assert inner_suite_span.get_tag("test.itr.unskippable") == "true" - - test_spans = [span for span in spans if span.get_tag("type") == "test"] - assert len(test_spans) == 7 - passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] - assert len(passed_test_spans) == 3 - skipped_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "skip"] - assert len(skipped_test_spans) == 4 - - test_inner_unskippable_span = [span for span in spans if span.get_tag("test.name") == "test_inner_unskippable"][ - 0 - ] - assert test_inner_unskippable_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_unskippable_span.get_tag("test.itr.forced_run") == "true" - - test_inner_shouldskip_skipif_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_shouldskip_skipif" - ][0] - assert test_inner_shouldskip_skipif_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_shouldskip_skipif_span.get_tag("test.status") == "skip" - - test_inner_shouldskip_skip_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_shouldskip_skip" - ][0] - assert test_inner_shouldskip_skip_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_shouldskip_skip_span.get_tag("test.status") == "skip" - - test_inner_wasnot_going_to_skip_skipif_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_wasnot_going_to_skip_skipif" - ][0] - assert test_inner_wasnot_going_to_skip_skipif_span.get_tag("test.itr.unskippable") == "true" - - def test_pytest_unskippable_tests_forced_run_in_suite_level(self): - package_outer_dir = self.testdir.mkpydir("test_outer_package") - os.chdir(str(package_outer_dir)) - with open("test_outer_abc.py", "w+") as fd: - fd.write( - textwrap.dedent( - ( - """ - def test_outer_ok(): - assert True - """ - ) - ) - ) - os.mkdir("test_inner_package") - os.chdir("test_inner_package") - with open("__init__.py", "w+"): - pass - with open("test_inner_abc.py", "w+") as fd: - fd.write( - textwrap.dedent( - """ - import pytest - def test_inner_ok(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_unskippable(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(True, reason="skipped anyway") - def test_inner_shouldskip_skipif(): - assert False - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skip(reason="just skip it") - def test_inner_shouldskip_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_itr_wont_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(False, reason="was not going to skip anyway") - def test_inner_wasnot_going_to_skip_skipif(): - assert True - """ - ) - ) - - self.testdir.chdir() - - _itr_data = ITRData( - skippable_items=_make_fqdn_suite_ids( - [ - ("test_outer_package.test_inner_package", "test_inner_abc.py"), - ("test_outer_package", "test_outer_abc.py"), - ] - ) - ) - - with mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", - side_effect=_fetch_test_to_skip_side_effect(_itr_data), - ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", - return_value=True, - ), mock.patch( + with override_env(dict(_DD_CIVISIBILITY_ITR_SUITE_MODE="True")), mock.patch( "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", return_value=True, - ), override_env( - {"_DD_CIVISIBILITY_ITR_SUITE_MODE": "True"} + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", + side_effect=_fetch_test_to_skip_side_effect(_itr_data), ), mock.patch( "ddtrace.internal.ci_visibility.recorder.ddconfig", _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), @@ -2796,79 +1891,36 @@ def test_inner_wasnot_going_to_skip_skipif(): self.inline_run("--ddtrace") spans = self.pop_spans() - assert len(spans) == 12 + assert len(spans) == 7 - session_span = _get_spans_from_list(spans, "session")[0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert session_span.get_tag("test.itr.unskippable") == "true" - assert session_span.get_tag("test.itr.forced_run") == "true" + session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] + assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" - module_spans = _get_spans_from_list(spans, "module") + module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] assert len(module_spans) == 2 + for module_span in module_spans: + assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - outer_module_span = _get_spans_from_list(module_spans, "module", "test_outer_package")[0] - assert outer_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert outer_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" - assert outer_module_span.get_tag("_dd.ci.itr.tests_skipped") == "true" - assert outer_module_span.get_tag("test.itr.forced_run") == "false" - - inner_module_span = _get_spans_from_list(module_spans, "module", "test_outer_package.test_inner_package")[0] - assert inner_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert inner_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert inner_module_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert inner_module_span.get_tag("test.itr.forced_run") == "true" - - test_suite_spans = _get_spans_from_list(spans, "suite") + test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] assert len(test_suite_spans) == 2 - inner_suite_span = _get_spans_from_list(test_suite_spans, "suite", "test_inner_abc.py")[0] - assert inner_suite_span.get_tag("test.itr.forced_run") == "true" - assert inner_suite_span.get_tag("test.itr.unskippable") == "true" - - test_spans = _get_spans_from_list(spans, "test") - assert len(test_spans) == 7 - passed_test_spans = _get_spans_from_list(test_spans, "test", status="pass") - assert len(passed_test_spans) == 4 - skipped_test_spans = _get_spans_from_list(test_spans, "test", status="skip") - assert len(skipped_test_spans) == 3 - - test_inner_ok_span = [span for span in spans if span.get_tag("test.name") == "test_inner_ok"][0] - assert test_inner_ok_span.get_tag("test.itr.forced_run") == "true" - - test_inner_unskippable_span = _get_spans_from_list(spans, "test", "test_inner_unskippable")[0] - assert test_inner_unskippable_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_unskippable_span.get_tag("test.itr.forced_run") == "true" - - test_inner_shouldskip_skipif_span = _get_spans_from_list(spans, "test", "test_inner_shouldskip_skipif")[0] - assert test_inner_shouldskip_skipif_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_shouldskip_skipif_span.get_tag("test.status") == "skip" - - test_inner_shouldskip_skip_span = _get_spans_from_list(spans, "test", "test_inner_shouldskip_skip")[0] - assert test_inner_shouldskip_skip_span.get_tag("test.itr.unskippable") == "true" - assert test_inner_shouldskip_skip_span.get_tag("test.status") == "skip" - - test_inner_wasnot_going_to_skip_skipif_span = _get_spans_from_list( - spans, "test", "test_inner_wasnot_going_to_skip_skipif" - )[0] - assert test_inner_wasnot_going_to_skip_skipif_span.get_tag("test.itr.unskippable") == "true" + test_spans = [span for span in spans if span.get_tag("type") == "test"] + assert len(test_spans) == 2 + passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] + assert len(passed_test_spans) == 2 - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_unskippable_none_skipped_in_test_level(self): - """When no tests are skipped, the test.itr.tests_skipping.tests_skipped tag should be false""" + def test_pytest_skip_tests_by_path_but_test_skipping_not_enabled(self): + """ + Test that running pytest on two nested packages with 1 test each. It should generate + 1 test session span, 2 test module spans, 2 test suite spans, and 2 test spans, + both suites are to be skipped with ITR, but test skipping is disabled. + """ package_outer_dir = self.testdir.mkpydir("test_outer_package") os.chdir(str(package_outer_dir)) with open("test_outer_abc.py", "w+") as fd: fd.write( - textwrap.dedent( - ( - """ - def test_outer_ok(): - assert True - """ - ) - ) + """def test_outer_ok(): + assert True""" ) os.mkdir("test_inner_package") os.chdir("test_inner_package") @@ -2876,45 +1928,17 @@ def test_outer_ok(): pass with open("test_inner_abc.py", "w+") as fd: fd.write( - textwrap.dedent( - """ - import pytest - def test_inner_ok(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_unskippable(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(True, reason="skipped anyway") - def test_inner_shouldskip_skipif(): - assert False - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skip(reason="just skip it") - def test_inner_shouldskip_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - def test_inner_itr_wont_skip(): - assert True - - @pytest.mark.skipif(False, reason="datadog_itr_unskippable") - @pytest.mark.skipif(False, reason="was not going to skip anyway") - def test_inner_wasnot_going_to_skip_skipif(): - assert True - """ - ) + """def test_inner_ok(): + assert True""" ) self.testdir.chdir() _itr_data = ITRData( skippable_items=_make_fqdn_test_ids( [ - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_unskippable"), + ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_ok"), ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skipif"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skip"), + ("test_outer_package", "test_outer_abc.py", "test_outer_ok"), ] ) ) @@ -2923,40 +1947,31 @@ def test_inner_wasnot_going_to_skip_skipif(): "ddtrace.internal.ci_visibility.recorder.CIVisibility._fetch_tests_to_skip", side_effect=_fetch_test_to_skip_side_effect(_itr_data), ), mock.patch( - "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", + "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", return_value=True, ): self.inline_run("--ddtrace") spans = self.pop_spans() - assert len(spans) == 12 + assert len(spans) == 7 session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] - assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert session_span.get_tag("test.itr.unskippable") == "true" - assert session_span.get_tag("test.itr.forced_run") == "true" + assert session_span.get_tag("test.itr.tests_skipping.enabled") == "false" module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] assert len(module_spans) == 2 + for module_span in module_spans: + assert module_span.get_tag("test.itr.tests_skipping.enabled") == "false" - outer_module_span = [span for span in module_spans if span.get_tag("test.module") == "test_outer_package"][0] - assert outer_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert outer_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert outer_module_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert outer_module_span.get_tag("test.itr.forced_run") == "false" + test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] + assert len(test_suite_spans) == 2 - inner_module_span = [ - span for span in module_spans if span.get_tag("test.module") == "test_outer_package.test_inner_package" - ][0] - assert inner_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" - assert inner_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" - assert inner_module_span.get_tag("_dd.ci.itr.tests_skipped") == "false" - assert inner_module_span.get_tag("test.itr.forced_run") == "true" + test_spans = [span for span in spans if span.get_tag("type") == "test"] + assert len(test_spans) == 2 + passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] + assert len(passed_test_spans) == 2 - @pytest.mark.skipif(_USE_PLUGIN_V2, reason="Pytest plugin v2 does not do test-level skipping") - def test_pytest_unskippable_suite_not_skipped_in_test_level(self): + def test_pytest_unskippable_tests_forced_run_in_suite_level(self): package_outer_dir = self.testdir.mkpydir("test_outer_package") os.chdir(str(package_outer_dir)) with open("test_outer_abc.py", "w+") as fd: @@ -2979,7 +1994,6 @@ def test_outer_ok(): textwrap.dedent( """ import pytest - pytestmark = pytest.mark.skipif(False, reason="datadog_itr_unskippable") def test_inner_ok(): assert True @@ -3008,16 +2022,14 @@ def test_inner_wasnot_going_to_skip_skipif(): """ ) ) + self.testdir.chdir() _itr_data = ITRData( - skippable_items=_make_fqdn_test_ids( + skippable_items=_make_fqdn_suite_ids( [ - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_ok"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_unskippable"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skipif"), - ("test_outer_package.test_inner_package", "test_inner_abc.py", "test_inner_shouldskip_skip"), - ("test_outer_package", "test_outer_abc.py", "test_outer_ok"), + ("test_outer_package.test_inner_package", "test_inner_abc.py"), + ("test_outer_package", "test_outer_abc.py"), ] ) ) @@ -3028,71 +2040,74 @@ def test_inner_wasnot_going_to_skip_skipif(): ), mock.patch( "ddtrace.internal.ci_visibility.recorder.CIVisibility.test_skipping_enabled", return_value=True, + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.CIVisibility.is_itr_enabled", + return_value=True, + ), override_env( + {"_DD_CIVISIBILITY_ITR_SUITE_MODE": "True"} + ), mock.patch( + "ddtrace.internal.ci_visibility.recorder.ddconfig", + _get_default_civisibility_ddconfig(ITR_SKIPPING_LEVEL.SUITE), ): self.inline_run("--ddtrace") spans = self.pop_spans() assert len(spans) == 12 - session_span = [span for span in spans if span.get_tag("type") == "test_session_end"][0] + session_span = _get_spans_from_list(spans, "session")[0] assert session_span.get_tag("test.itr.tests_skipping.enabled") == "true" assert session_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" assert session_span.get_tag("_dd.ci.itr.tests_skipped") == "true" assert session_span.get_tag("test.itr.unskippable") == "true" assert session_span.get_tag("test.itr.forced_run") == "true" - module_spans = [span for span in spans if span.get_tag("type") == "test_module_end"] + module_spans = _get_spans_from_list(spans, "module") assert len(module_spans) == 2 - outer_module_span = [span for span in module_spans if span.get_tag("test.module") == "test_outer_package"][0] + outer_module_span = _get_spans_from_list(module_spans, "module", "test_outer_package")[0] assert outer_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" assert outer_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "true" assert outer_module_span.get_tag("_dd.ci.itr.tests_skipped") == "true" assert outer_module_span.get_tag("test.itr.forced_run") == "false" - inner_module_span = [ - span for span in module_spans if span.get_tag("test.module") == "test_outer_package.test_inner_package" - ][0] + inner_module_span = _get_spans_from_list(module_spans, "module", "test_outer_package.test_inner_package")[0] assert inner_module_span.get_tag("test.itr.tests_skipping.enabled") == "true" assert inner_module_span.get_tag("test.itr.tests_skipping.tests_skipped") == "false" assert inner_module_span.get_tag("_dd.ci.itr.tests_skipped") == "false" assert inner_module_span.get_tag("test.itr.forced_run") == "true" - test_suite_spans = [span for span in spans if span.get_tag("type") == "test_suite_end"] + test_suite_spans = _get_spans_from_list(spans, "suite") assert len(test_suite_spans) == 2 - inner_suite_span = [span for span in test_suite_spans if span.get_tag("test.suite") == "test_inner_abc.py"][0] + inner_suite_span = _get_spans_from_list(test_suite_spans, "suite", "test_inner_abc.py")[0] assert inner_suite_span.get_tag("test.itr.forced_run") == "true" assert inner_suite_span.get_tag("test.itr.unskippable") == "true" - test_spans = [span for span in spans if span.get_tag("type") == "test"] + test_spans = _get_spans_from_list(spans, "test") assert len(test_spans) == 7 - passed_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "pass"] + passed_test_spans = _get_spans_from_list(test_spans, "test", status="pass") assert len(passed_test_spans) == 4 - skipped_test_spans = [x for x in spans if x.get_tag("type") == "test" and x.get_tag("test.status") == "skip"] + skipped_test_spans = _get_spans_from_list(test_spans, "test", status="skip") assert len(skipped_test_spans) == 3 - test_inner_unskippable_span = [span for span in spans if span.get_tag("test.name") == "test_inner_unskippable"][ - 0 - ] + test_inner_ok_span = [span for span in spans if span.get_tag("test.name") == "test_inner_ok"][0] + assert test_inner_ok_span.get_tag("test.itr.forced_run") == "true" + + test_inner_unskippable_span = _get_spans_from_list(spans, "test", "test_inner_unskippable")[0] assert test_inner_unskippable_span.get_tag("test.itr.unskippable") == "true" assert test_inner_unskippable_span.get_tag("test.itr.forced_run") == "true" - test_inner_shouldskip_skipif_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_shouldskip_skipif" - ][0] + test_inner_shouldskip_skipif_span = _get_spans_from_list(spans, "test", "test_inner_shouldskip_skipif")[0] assert test_inner_shouldskip_skipif_span.get_tag("test.itr.unskippable") == "true" assert test_inner_shouldskip_skipif_span.get_tag("test.status") == "skip" - test_inner_shouldskip_skip_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_shouldskip_skip" - ][0] + test_inner_shouldskip_skip_span = _get_spans_from_list(spans, "test", "test_inner_shouldskip_skip")[0] assert test_inner_shouldskip_skip_span.get_tag("test.itr.unskippable") == "true" assert test_inner_shouldskip_skip_span.get_tag("test.status") == "skip" - test_inner_wasnot_going_to_skip_skipif_span = [ - span for span in spans if span.get_tag("test.name") == "test_inner_wasnot_going_to_skip_skipif" - ][0] + test_inner_wasnot_going_to_skip_skipif_span = _get_spans_from_list( + spans, "test", "test_inner_wasnot_going_to_skip_skipif" + )[0] assert test_inner_wasnot_going_to_skip_skipif_span.get_tag("test.itr.unskippable") == "true" def test_pytest_unskippable_suite_not_skipped_in_suite_level(self): @@ -3506,42 +2521,23 @@ def test_inner_package_module_class_two_ok(self): sorted_test_names = sorted([span.get_tag("test.name") for span in spans if span.get_tag("type") == "test"]) assert len(sorted_test_names) == 15 - if _USE_PLUGIN_V2: - assert sorted_test_names == [ - "TestInnerPackageClassOne::test_inner_package_class_one_ok", - "TestInnerPackageClassTwo::test_inner_package_class_two_ok", - "TestInnerPackageModuleClassOne::test_inner_package_module_class_one_ok", - "TestInnerPackageModuleClassTwo::test_inner_package_module_class_two_ok", - "TestOuterMostClassOne::test_outermost_ok", - "TestOuterMostClassTwo::test_outermost_ok", - "TestOuterPackageClassOne::test_outer_package_class_one_ok", - "TestOuterPackageClassTwo::test_outer_package_class_two_ok", - "TestOuterPackageModuleClassOne::test_outer_package_module_class_one_ok", - "TestOuterPackageModuleClassTwo::test_outer_package_module_class_two_ok", - "test_inner_package_module_test_ok", - "test_inner_package_ok", - "test_outer_package_module_ok", - "test_outer_package_ok", - "test_outermost_test_ok", - ] - else: - assert sorted_test_names == [ - "test_inner_package_class_one_ok", - "test_inner_package_class_two_ok", - "test_inner_package_module_class_one_ok", - "test_inner_package_module_class_two_ok", - "test_inner_package_module_test_ok", - "test_inner_package_ok", - "test_outer_package_class_one_ok", - "test_outer_package_class_two_ok", - "test_outer_package_module_class_one_ok", - "test_outer_package_module_class_two_ok", - "test_outer_package_module_ok", - "test_outer_package_ok", - "test_outermost_ok", - "test_outermost_ok", - "test_outermost_test_ok", - ] + assert sorted_test_names == [ + "TestInnerPackageClassOne::test_inner_package_class_one_ok", + "TestInnerPackageClassTwo::test_inner_package_class_two_ok", + "TestInnerPackageModuleClassOne::test_inner_package_module_class_one_ok", + "TestInnerPackageModuleClassTwo::test_inner_package_module_class_two_ok", + "TestOuterMostClassOne::test_outermost_ok", + "TestOuterMostClassTwo::test_outermost_ok", + "TestOuterPackageClassOne::test_outer_package_class_one_ok", + "TestOuterPackageClassTwo::test_outer_package_class_two_ok", + "TestOuterPackageModuleClassOne::test_outer_package_module_class_one_ok", + "TestOuterPackageModuleClassTwo::test_outer_package_module_class_two_ok", + "test_inner_package_module_test_ok", + "test_inner_package_ok", + "test_outer_package_module_ok", + "test_outer_package_ok", + "test_outermost_test_ok", + ] def test_pytest_ddtrace_test_names_include_class_opt(self): package_outer_dir = self.testdir.mkpydir("test_package") @@ -3590,15 +2586,11 @@ def test_ok(self): assert test_spans[1].get_tag("test.module") == "test_package" assert test_spans[1].get_tag("test.suite") == "test_names.py" - assert test_spans[1].get_tag("test.name") == ( - "TestClassOne::test_ok" if _USE_PLUGIN_V2 else "TestClassOne.test_ok" - ) + assert test_spans[1].get_tag("test.name") == "TestClassOne::test_ok" assert test_spans[2].get_tag("test.module") == "test_package" assert test_spans[2].get_tag("test.suite") == "test_names.py" - assert test_spans[2].get_tag("test.name") == ( - "TestClassTwo::test_ok" if _USE_PLUGIN_V2 else "TestClassTwo.test_ok" - ) + assert test_spans[2].get_tag("test.name") == "TestClassTwo::test_ok" def test_pytest_ddtrace_name_hooks(self): """This only tests that whatever hooks a user defines are being used""" @@ -3714,16 +2706,12 @@ def test_my_string_test(): assert test_spans[0].get_metric("test.source.start") == 8 assert test_spans[0].get_metric("test.source.end") == 11 - assert test_spans[1].get_tag("test.name") == ( - "TestClassOne::test_my_second_test" if _USE_PLUGIN_V2 else "test_my_second_test" - ) + assert test_spans[1].get_tag("test.name") == "TestClassOne::test_my_second_test" assert test_spans[1].get_tag("test.source.file") == "test_source_package/test_names.py" assert test_spans[1].get_metric("test.source.start") == 13 assert test_spans[1].get_metric("test.source.end") == 16 - assert test_spans[2].get_tag("test.name") == ( - "TestClassTwo::test_my_third_test" if _USE_PLUGIN_V2 else "test_my_third_test" - ) + assert test_spans[2].get_tag("test.name") == "TestClassTwo::test_my_third_test" assert test_spans[2].get_tag("test.source.file") == "test_source_package/test_names.py" assert test_spans[2].get_metric("test.source.start") == 18 assert test_spans[2].get_metric("test.source.end") == 20 diff --git a/tests/contrib/pytest/test_pytest_atr.py b/tests/contrib/pytest/test_pytest_atr.py index 1883230cb7b..9bb61528a8c 100644 --- a/tests/contrib/pytest/test_pytest_atr.py +++ b/tests/contrib/pytest/test_pytest_atr.py @@ -11,7 +11,6 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_atr from ddtrace.internal.ci_visibility._api_client import TestVisibilityAPISettings from tests.ci_visibility.util import _get_default_civisibility_ddconfig @@ -19,10 +18,7 @@ from tests.contrib.pytest.test_pytest import _get_spans_from_list -pytestmark = pytest.mark.skipif( - not (_USE_PLUGIN_V2 and _pytest_version_supports_atr()), - reason="Auto Test Retries requires v2 of the plugin and pytest >=7.0", -) +pytestmark = pytest.mark.skipif(not _pytest_version_supports_atr(), reason="Auto Test Retries requires pytest >=7.0") _TEST_PASS_CONTENT = """ import unittest diff --git a/tests/contrib/pytest/test_pytest_attempt_to_fix.py b/tests/contrib/pytest/test_pytest_attempt_to_fix.py index 178017ea39e..a77467f0ccc 100644 --- a/tests/contrib/pytest/test_pytest_attempt_to_fix.py +++ b/tests/contrib/pytest/test_pytest_attempt_to_fix.py @@ -5,7 +5,6 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_attempt_to_fix from ddtrace.internal.ci_visibility._api_client import ITRData from ddtrace.internal.ci_visibility._api_client import TestManagementSettings @@ -19,8 +18,7 @@ pytestmark = pytest.mark.skipif( - not (_USE_PLUGIN_V2 and _pytest_version_supports_attempt_to_fix()), - reason="Attempt-to-Fix requires v2 of the plugin and pytest >=7.0", + not _pytest_version_supports_attempt_to_fix(), reason="Attempt-to-Fix requires pytest >=7.0" ) _TEST_PASS = """ diff --git a/tests/contrib/pytest/test_pytest_disabling.py b/tests/contrib/pytest/test_pytest_disabling.py index 5b88c28ce1c..bf295e86014 100644 --- a/tests/contrib/pytest/test_pytest_disabling.py +++ b/tests/contrib/pytest/test_pytest_disabling.py @@ -3,7 +3,6 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_efd from ddtrace.internal.ci_visibility._api_client import TestManagementSettings from ddtrace.internal.ci_visibility._api_client import TestProperties @@ -14,10 +13,7 @@ from tests.contrib.pytest.utils import assert_stats -pytestmark = pytest.mark.skipif( - not (_USE_PLUGIN_V2 and _pytest_version_supports_efd()), - reason="Quarantine requires v2 of the plugin and pytest >=7.0", -) +pytestmark = pytest.mark.skipif(not _pytest_version_supports_efd(), reason="Disabling requires pytest >=7.0") _TEST_PROPERTIES = { diff --git a/tests/contrib/pytest/test_pytest_efd.py b/tests/contrib/pytest/test_pytest_efd.py index 25f63c71d91..df06c59082e 100644 --- a/tests/contrib/pytest/test_pytest_efd.py +++ b/tests/contrib/pytest/test_pytest_efd.py @@ -11,7 +11,6 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_efd from ddtrace.internal.ci_visibility._api_client import EarlyFlakeDetectionSettings from ddtrace.internal.ci_visibility._api_client import TestVisibilityAPISettings @@ -24,8 +23,7 @@ pytestmark = pytest.mark.skipif( - not (_USE_PLUGIN_V2 and _pytest_version_supports_efd()), - reason="Early Flake Detection requires v2 of the plugin and pytest >=7.0", + not _pytest_version_supports_efd(), reason="Early Flake Detection requires pytest >=7.0" ) _KNOWN_TEST_IDS = _make_fqdn_test_ids( diff --git a/tests/contrib/pytest/test_pytest_quarantine.py b/tests/contrib/pytest/test_pytest_quarantine.py index 1f8e99682a5..34f896f681a 100644 --- a/tests/contrib/pytest/test_pytest_quarantine.py +++ b/tests/contrib/pytest/test_pytest_quarantine.py @@ -10,7 +10,6 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.contrib.internal.pytest._utils import _pytest_version_supports_efd from ddtrace.internal.ci_visibility._api_client import TestManagementSettings from ddtrace.internal.ci_visibility._api_client import TestProperties @@ -21,10 +20,7 @@ from tests.contrib.pytest.utils import assert_stats -pytestmark = pytest.mark.skipif( - not (_USE_PLUGIN_V2 and _pytest_version_supports_efd()), - reason="Quarantine requires v2 of the plugin and pytest >=7.0", -) +pytestmark = pytest.mark.skipif(not _pytest_version_supports_efd(), reason="Quarantine requires pytest >=7.0") _TEST_PASS_QUARANTINED = """ import pytest diff --git a/tests/contrib/pytest/test_pytest_snapshot.py b/tests/contrib/pytest/test_pytest_snapshot.py deleted file mode 100644 index 17876eea2f0..00000000000 --- a/tests/contrib/pytest/test_pytest_snapshot.py +++ /dev/null @@ -1,173 +0,0 @@ -import subprocess -from unittest import mock - -import pytest - -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 -from ddtrace.internal.ci_visibility._api_client import TestVisibilityAPISettings -from tests.ci_visibility.util import _get_default_ci_env_vars -from tests.utils import TracerTestCase -from tests.utils import snapshot - - -pytestmark = pytest.mark.skipif(_USE_PLUGIN_V2, reason="Tests in this module are for v1 of the pytest plugin") - -SNAPSHOT_IGNORES = [ - "meta.ci.workspace_path", - "meta.error.stack", - "meta.library_version", - "meta.os.architecture", - "meta.os.platform", - "meta.os.version", - "meta.runtime-id", - "meta.runtime.version", - "meta.test.framework_version", - "meta.test_module_id", - "meta.test_session_id", - "meta.test_suite_id", - "metrics._dd.top_level", - "metrics._dd.tracer_kr", - "metrics._sampling_priority_v1", - "metrics.process_id", - "duration", - "start", -] -SNAPSHOT_IGNORES_PATCH_ALL = SNAPSHOT_IGNORES + ["meta.http.useragent"] - -SNAPSHOT_IGNORES_ITR_COVERAGE = ["metrics.test.source.start", "metrics.test.source.end", "meta.test.source.file"] - - -class PytestSnapshotTestCase(TracerTestCase): - @pytest.fixture(autouse=True) - def fixtures(self, testdir, monkeypatch, git_repo): - self.testdir = testdir - self.monkeypatch = monkeypatch - self.git_repo = git_repo - - @snapshot(ignores=SNAPSHOT_IGNORES) - def test_pytest_will_include_lines_pct(self): - tools = """ - def add_two_number_list(list_1, list_2): - output_list = [] - for number_a, number_b in zip(list_1, list_2): - output_list.append(number_a + number_b) - return output_list - - def multiply_two_number_list(list_1, list_2): - output_list = [] - for number_a, number_b in zip(list_1, list_2): - output_list.append(number_a * number_b) - return output_list - """ - self.testdir.makepyfile(tools=tools) - test_tools = """ - from tools import add_two_number_list - - def test_add_two_number_list(): - a_list = [1,2,3,4,5,6,7,8] - b_list = [2,3,4,5,6,7,8,9] - actual_output = add_two_number_list(a_list, b_list) - - assert actual_output == [3,5,7,9,11,13,15,17] - """ - self.testdir.makepyfile(test_tools=test_tools) - self.testdir.chdir() - with mock.patch( - "ddtrace.internal.ci_visibility._api_client._TestVisibilityAPIClientBase.fetch_settings", - return_value=TestVisibilityAPISettings(False, False, False, False), - ): - subprocess.run( - ["ddtrace-run", "coverage", "run", "--include=tools.py", "-m", "pytest", "--ddtrace"], - env=_get_default_ci_env_vars( - dict( - DD_API_KEY="foobar.baz", - DD_CIVISIBILITY_ITR_ENABLED="false", - DD_PATCH_MODULES="sqlite3:false", - CI_PROJECT_DIR=str(self.testdir.tmpdir), - DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN="true", - ) - ), - ) - - @snapshot(ignores=SNAPSHOT_IGNORES) - def test_pytest_wont_include_lines_pct_if_report_empty(self): - tools = """ - def add_two_number_list(list_1, list_2): - output_list = [] - for number_a, number_b in zip(list_1, list_2): - output_list.append(number_a + number_b) - return output_list - - def multiply_two_number_list(list_1, list_2): - output_list = [] - for number_a, number_b in zip(list_1, list_2): - output_list.append(number_a * number_b) - return output_list - """ - self.testdir.makepyfile(tools=tools) - test_tools = """ - from tools import add_two_number_list - - def test_add_two_number_list(): - a_list = [1,2,3,4,5,6,7,8] - b_list = [2,3,4,5,6,7,8,9] - actual_output = add_two_number_list(a_list, b_list) - - assert actual_output == [3,5,7,9,11,13,15,17] - """ - self.testdir.makepyfile(test_tools=test_tools) - self.testdir.chdir() - with mock.patch( - "ddtrace.internal.ci_visibility._api_client._TestVisibilityAPIClientBase.fetch_settings", - return_value=TestVisibilityAPISettings(False, False, False, False), - ): - subprocess.run( - ["ddtrace-run", "coverage", "run", "--include=nothing.py", "-m", "pytest", "--ddtrace"], - env=_get_default_ci_env_vars( - dict( - DD_API_KEY="foobar.baz", - DD_CIVISIBILITY_ITR_ENABLED="false", - DD_PATCH_MODULES="sqlite3:false", - CI_PROJECT_DIR=str(self.testdir.tmpdir), - DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN="true", - ) - ), - ) - - @snapshot(ignores=SNAPSHOT_IGNORES_PATCH_ALL) - def test_pytest_with_ddtrace_patch_all(self): - call_httpx = """ - import httpx - - def call_httpx(): - return httpx.get("http://localhost:9126/bad_path.cgi") - """ - self.testdir.makepyfile(call_httpx=call_httpx) - test_call_httpx = """ - from call_httpx import call_httpx - - def test_call_urllib(): - r = call_httpx() - assert r.status_code == 404 - """ - self.testdir.makepyfile(test_call_httpx=test_call_httpx) - self.testdir.chdir() - with mock.patch( - "ddtrace.internal.ci_visibility._api_client._TestVisibilityAPIClientBase.fetch_settings", - return_value=TestVisibilityAPISettings(False, False, False, False), - ): - subprocess.run( - ["pytest", "--ddtrace", "--ddtrace-patch-all"], - env=_get_default_ci_env_vars( - dict( - DD_API_KEY="foobar.baz", - DD_CIVISIBILITY_ITR_ENABLED="false", - CI_PROJECT_DIR=str(self.testdir.tmpdir), - DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN="true", - DD_PATCH_MODULES="httpx:true", - ) - ), - ) diff --git a/tests/contrib/pytest/test_pytest_snapshot_v2.py b/tests/contrib/pytest/test_pytest_snapshot_v2.py index f7a123129a6..e2750d04aec 100644 --- a/tests/contrib/pytest/test_pytest_snapshot_v2.py +++ b/tests/contrib/pytest/test_pytest_snapshot_v2.py @@ -3,15 +3,12 @@ import pytest -from ddtrace.contrib.internal.pytest._utils import _USE_PLUGIN_V2 from ddtrace.internal.ci_visibility._api_client import TestVisibilityAPISettings from tests.ci_visibility.util import _get_default_ci_env_vars from tests.utils import TracerTestCase from tests.utils import snapshot -pytestmark = pytest.mark.skipif(not _USE_PLUGIN_V2, reason="Tests in this module are for v2 of the pytest plugin") - SNAPSHOT_IGNORES = [ "meta.ci.workspace_path", "meta.error.stack", diff --git a/tests/contrib/selenium/test_selenium_chrome.py b/tests/contrib/selenium/test_selenium_chrome.py index d820e384113..71531e57808 100644 --- a/tests/contrib/selenium/test_selenium_chrome.py +++ b/tests/contrib/selenium/test_selenium_chrome.py @@ -116,7 +116,6 @@ def test_selenium_local_pass(): DD_PATCH_MODULES="sqlite3:false", CI_PROJECT_DIR=str(testdir.tmpdir), DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN=os.environ.get("_TESTED_PYTEST_LEGACY_PLUGIN"), ) ), ) @@ -167,7 +166,6 @@ def test_selenium_local_pass(): DD_PATCH_MODULES="sqlite3:false", CI_PROJECT_DIR=str(testdir.tmpdir), DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN=os.environ.get("_TESTED_PYTEST_LEGACY_PLUGIN"), ) ), ) @@ -221,7 +219,6 @@ def test_selenium_local_unpatch(): DD_PATCH_MODULES="sqlite3:false", CI_PROJECT_DIR=str(testdir.tmpdir), DD_CIVISIBILITY_AGENTLESS_ENABLED="false", - _DD_PYTEST_USE_LEGACY_PLUGIN=os.environ.get("_TESTED_PYTEST_LEGACY_PLUGIN"), ) ), )