From d03d8ccec14328e15be5033824c9512259372838 Mon Sep 17 00:00:00 2001 From: Ben Kunkle Date: Wed, 30 Apr 2025 13:26:30 -0400 Subject: [PATCH] python: Fix identification of runnable tests within decorated test classes (#29688) Closes #29486 Release Notes: - python: Fixed identification of runnable test functions within decorated pytest classes --- crates/languages/src/python/runnables.scm | 109 ++++++++++++++-------- 1 file changed, 70 insertions(+), 39 deletions(-) diff --git a/crates/languages/src/python/runnables.scm b/crates/languages/src/python/runnables.scm index 84a024de94..1c7e76d73b 100644 --- a/crates/languages/src/python/runnables.scm +++ b/crates/languages/src/python/runnables.scm @@ -4,12 +4,12 @@ name: (identifier) @run @_unittest_class_name superclasses: (argument_list [(identifier) @_superclass - (attribute (identifier) @_superclass)] - ) + (attribute (identifier) @_superclass)] + ) (#eq? @_superclass "TestCase") - ) @_python-unittest-class + ) @_python-unittest-class (#set! tag python-unittest-class) -) + ) ; test methods whose names start with `test` in a TestCase ( @@ -17,18 +17,18 @@ name: (identifier) @_unittest_class_name superclasses: (argument_list [(identifier) @_superclass - (attribute (identifier) @_superclass)] - ) + (attribute (identifier) @_superclass)] + ) (#eq? @_superclass "TestCase") body: (block - (function_definition - name: (identifier) @run @_unittest_method_name - (#match? @_unittest_method_name "^test.*") + (function_definition + name: (identifier) @run @_unittest_method_name + (#match? @_unittest_method_name "^test.*") ) @_python-unittest-method - (#set! tag python-unittest-method) + (#set! tag python-unittest-method) ) ) -) + ) ; pytest functions ( @@ -36,10 +36,10 @@ (function_definition name: (identifier) @run @_pytest_method_name (#match? @_pytest_method_name "^test_") - ) @_python-pytest-method - ) + ) @_python-pytest-method + ) (#set! tag python-pytest-method) -) + ) ; decorated pytest functions ( @@ -53,7 +53,8 @@ ) @_python-pytest-method ) (#set! tag python-pytest-method) -) + ) + ; pytest classes ( @@ -61,10 +62,26 @@ (class_definition name: (identifier) @run @_pytest_class_name (#match? @_pytest_class_name "^Test") - ) + ) (#set! tag python-pytest-class) + ) ) -) + + +; decorated pytest classes +( + (module + (decorated_definition + (decorator)+ @_decorator + definition: (class_definition + name: (identifier) @run @_pytest_class_name + (#match? @_pytest_class_name "^Test") + ) + ) + (#set! tag python-pytest-class) + ) + ) + ; pytest class methods ( @@ -73,35 +90,49 @@ name: (identifier) @_pytest_class_name (#match? @_pytest_class_name "^Test") body: (block - (function_definition - name: (identifier) @run @_pytest_method_name - (#match? @_pytest_method_name "^test") - ) @_python-pytest-method - (#set! tag python-pytest-method) - ) - ) - ) -) - -; decorated pytest class methods -( - (module - (class_definition - name: (identifier) @_pytest_class_name - (#match? @_pytest_class_name "^Test") - body: (block - (decorated_definition + [(decorated_definition (decorator)+ @_decorator definition: (function_definition name: (identifier) @run @_pytest_method_name (#match? @_pytest_method_name "^test_") ) ) - ) @_python-pytest-method + (function_definition + name: (identifier) @run @_pytest_method_name + (#match? @_pytest_method_name "^test") + ) + ] @_python-pytest-method) (#set! tag python-pytest-method) + ) + ) + ) + +; decorated pytest class methods +( + (module + (decorated_definition + (decorator)+ @_decorator + definition: (class_definition + name: (identifier) @_pytest_class_name + (#match? @_pytest_class_name "^Test") + body: (block + [(decorated_definition + (decorator)+ @_decorator + definition: (function_definition + name: (identifier) @run @_pytest_method_name + (#match? @_pytest_method_name "^test_") + ) + ) + (function_definition + name: (identifier) @run @_pytest_method_name + (#match? @_pytest_method_name "^test") + ) + ] @_python-pytest-method) + (#set! tag python-pytest-method) + ) + ) ) ) -) ; module main method ( @@ -111,10 +142,10 @@ (identifier) @run @_lhs operators: "==" (string) @_rhs - ) + ) (#eq? @_lhs "__name__") (#match? @_rhs "^[\"']__main__[\"']$") (#set! tag python-module-main-method) + ) ) ) -)