From 7bcb3bc6f72595047f5aeca7fe431b49af94fca0 Mon Sep 17 00:00:00 2001 From: Nahuel Espinosa Date: Sat, 28 Jun 2025 16:22:12 -0300 Subject: [PATCH] fix(py_test): Support target names with a `test_` prefix Signed-off-by: Nahuel Espinosa --- docs/py_test.md | 3 ++- examples/pytest/BUILD.bazel | 10 ++++++++++ examples/pytest/prefix_test.py | 2 ++ py/defs.bzl | 7 +++++-- py/private/py_pytest_main.bzl | 5 +++-- 5 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 examples/pytest/prefix_test.py diff --git a/docs/py_test.md b/docs/py_test.md index ea1294df..ca5265a2 100644 --- a/docs/py_test.md +++ b/docs/py_test.md @@ -72,7 +72,7 @@ Run a Python program under Bazel. Most users should use the [py_test macro](#py_ ## py_pytest_main
-py_pytest_main(name, py_library, deps, data, testonly, kwargs)
+py_pytest_main(name, test_main, py_library, deps, data, testonly, kwargs)
 
py_pytest_main wraps the template rendering target and the final py_library. @@ -83,6 +83,7 @@ py_pytest_main wraps the template rendering target and the final py_library. | Name | Description | Default Value | | :------------- | :------------- | :------------- | | name | The name of the runable target that updates the test entry file. | none | +| test_main | The name of the test entry file to be generated. | None | | py_library | Use this attribute to override the default py_library rule. | <unknown object com.google.devtools.build.skydoc.fakebuildapi.FakeStarlarkRuleFunctionsApi$RuleDefinitionIdentifier> | | deps | A list containing the pytest library target, e.g., @pypi_pytest//:pkg. | [] | | data | A list of data dependencies to pass to the py_library target. | [] | diff --git a/examples/pytest/BUILD.bazel b/examples/pytest/BUILD.bazel index 9256da54..36425658 100644 --- a/examples/pytest/BUILD.bazel +++ b/examples/pytest/BUILD.bazel @@ -38,3 +38,13 @@ py_test( shard_count = 2, deps = ["@pypi_pytest//:pkg"], ) + +py_test( + # NB: target name starts with a test_ prefix + name = "test_prefix", + srcs = ["prefix_test.py"], + pytest_main = True, + deps = [ + "@pypi_pytest//:pkg", + ], +) diff --git a/examples/pytest/prefix_test.py b/examples/pytest/prefix_test.py new file mode 100644 index 00000000..f186a7e6 --- /dev/null +++ b/examples/pytest/prefix_test.py @@ -0,0 +1,2 @@ +def test_always_passing(): + assert True diff --git a/py/defs.bzl b/py/defs.bzl index b23ded39..79ca203f 100644 --- a/py/defs.bzl +++ b/py/defs.bzl @@ -163,8 +163,11 @@ def py_test(name, srcs = [], main = None, pytest_main = False, **kwargs): if main: fail("When pytest_main is set, the main attribute should not be set.") pytest_main_target = name + ".pytest_main" - main = pytest_main_target + ".py" - py_pytest_main(name = pytest_main_target) + + # NB: The main name starts with a dot, so pytest does not mistakenly collect + # the file during test collection even if the target name starts with `test_`. + main = "." + pytest_main_target + ".py" + py_pytest_main(name = pytest_main_target, test_main = main) srcs.append(main) deps.append(pytest_main_target) diff --git a/py/private/py_pytest_main.bzl b/py/private/py_pytest_main.bzl index 4ce6292a..f311d3ed 100644 --- a/py/private/py_pytest_main.bzl +++ b/py/private/py_pytest_main.bzl @@ -58,11 +58,12 @@ _py_pytest_main = rule( }, ) -def py_pytest_main(name, py_library = default_py_library, deps = [], data = [], testonly = True, **kwargs): +def py_pytest_main(name, test_main = None, py_library = default_py_library, deps = [], data = [], testonly = True, **kwargs): """py_pytest_main wraps the template rendering target and the final py_library. Args: name: The name of the runable target that updates the test entry file. + test_main: The name of the test entry file to be generated. py_library: Use this attribute to override the default py_library rule. deps: A list containing the pytest library target, e.g., @pypi_pytest//:pkg. data: A list of data dependencies to pass to the py_library target. @@ -70,7 +71,7 @@ def py_pytest_main(name, py_library = default_py_library, deps = [], data = [], **kwargs: The extra arguments passed to the template rendering target. """ - test_main = name + ".py" + test_main = test_main or name + ".py" tags = kwargs.pop("tags", []) visibility = kwargs.pop("visibility", [])