tests: make toolchain tests run in the same build instead of bazel-in-bazel integration tests (#2095)

This changes the //tests/toolchains tests to run in the same Bazel build
instance instead of
being bazel-in-bazel integration tests. This is done by using a
transition to set
the python version to match the desired toolchain.

This makes running the tests **much** cheaper -- there were 37 sub-bazel
processes being
started (one for each python version), which was very expensive.
Debugging is also much easier because they aren't part of a
bazel-in-bazel invocation.
diff --git a/MODULE.bazel b/MODULE.bazel
index 2e0d06d..457d8cc 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -76,6 +76,15 @@
 bazel_dep(name = "rules_go", version = "0.41.0", dev_dependency = True, repo_name = "io_bazel_rules_go")
 bazel_dep(name = "gazelle", version = "0.33.0", dev_dependency = True, repo_name = "bazel_gazelle")
 
+dev_python = use_extension(
+    "//python/extensions:python.bzl",
+    "python",
+    dev_dependency = True,
+)
+dev_python.rules_python_private_testing(
+    register_all_versions = True,
+)
+
 dev_pip = use_extension(
     "//python/private/pypi:pip.bzl",
     "pip_internal",
diff --git a/WORKSPACE b/WORKSPACE
index 90e9305..6c1ab4f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -42,12 +42,13 @@
 rules_python_internal_setup()
 
 load("//python:repositories.bzl", "python_register_multi_toolchains")
-load("//python:versions.bzl", "MINOR_MAPPING")
+load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS")
 
 python_register_multi_toolchains(
     name = "python",
     default_version = MINOR_MAPPING.values()[-2],
-    python_versions = MINOR_MAPPING.values(),
+    # Integration tests verify each version, so register all of them.
+    python_versions = TOOL_VERSIONS.keys(),
 )
 
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
diff --git a/python/private/python.bzl b/python/private/python.bzl
index 2791ae9..ce00a7b 100644
--- a/python/private/python.bzl
+++ b/python/private/python.bzl
@@ -16,6 +16,7 @@
 
 load("@bazel_features//:features.bzl", "bazel_features")
 load("//python:repositories.bzl", "python_register_toolchains")
+load("//python:versions.bzl", "TOOL_VERSIONS")
 load(":pythons_hub.bzl", "hub_repo")
 load(":text_util.bzl", "render")
 load(":toolchains_repo.bzl", "multi_toolchain_aliases")
@@ -78,7 +79,9 @@
     for mod in module_ctx.modules:
         module_toolchain_versions = []
 
-        for toolchain_attr in mod.tags.toolchain:
+        toolchain_attr_structs = _create_toolchain_attr_structs(mod)
+
+        for toolchain_attr in toolchain_attr_structs:
             toolchain_version = toolchain_attr.python_version
             toolchain_name = "python_" + toolchain_version.replace(".", "_")
 
@@ -95,9 +98,7 @@
                 # * rules_python needs to set a soft default in case the root module doesn't,
                 #   e.g. if the root module doesn't use Python itself.
                 # * The root module is allowed to override the rules_python default.
-
-                # A single toolchain is treated as the default because it's unambiguous.
-                is_default = toolchain_attr.is_default or len(mod.tags.toolchain) == 1
+                is_default = toolchain_attr.is_default
 
                 # Also only the root module should be able to decide ignore_root_user_error.
                 # Modules being depended upon don't know the final environment, so they aren't
@@ -251,6 +252,43 @@
         second = second,
     ))
 
+def _create_toolchain_attr_structs(mod):
+    arg_structs = []
+    seen_versions = {}
+    for tag in mod.tags.toolchain:
+        arg_structs.append(_create_toolchain_attrs_struct(tag = tag, toolchain_tag_count = len(mod.tags.toolchain)))
+        seen_versions[tag.python_version] = True
+
+    if mod.is_root:
+        register_all = False
+        for tag in mod.tags.rules_python_private_testing:
+            if tag.register_all_versions:
+                register_all = True
+                break
+        if register_all:
+            arg_structs.extend([
+                _create_toolchain_attrs_struct(python_version = v)
+                for v in TOOL_VERSIONS.keys()
+                if v not in seen_versions
+            ])
+    return arg_structs
+
+def _create_toolchain_attrs_struct(*, tag = None, python_version = None, toolchain_tag_count = None):
+    if tag and python_version:
+        fail("Only one of tag and python version can be specified")
+    if tag:
+        # A single toolchain is treated as the default because it's unambiguous.
+        is_default = tag.is_default or toolchain_tag_count == 1
+    else:
+        is_default = False
+
+    return struct(
+        is_default = is_default,
+        python_version = python_version if python_version else tag.python_version,
+        configure_coverage_tool = getattr(tag, "configure_coverage_tool", False),
+        ignore_root_user_error = getattr(tag, "ignore_root_user_error", False),
+    )
+
 def _get_bazel_version_specific_kwargs():
     kwargs = {}
 
@@ -264,6 +302,11 @@
 """,
     implementation = _python_impl,
     tag_classes = {
+        "rules_python_private_testing": tag_class(
+            attrs = {
+                "register_all_versions": attr.bool(default = False),
+            },
+        ),
         "toolchain": tag_class(
             doc = """Tag class used to register Python toolchains.
 Use this tag class to register one or more Python toolchains. This class
diff --git a/tests/support/sh_py_run_test.bzl b/tests/support/sh_py_run_test.bzl
index 183122a..455f64e 100644
--- a/tests/support/sh_py_run_test.bzl
+++ b/tests/support/sh_py_run_test.bzl
@@ -20,16 +20,18 @@
 load("//python:py_binary.bzl", "py_binary")
 load("//python:py_test.bzl", "py_test")
 load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE")  # buildifier: disable=bzl-visibility
+load("//tests/support:support.bzl", "VISIBLE_FOR_TESTING")
 
 def _perform_transition_impl(input_settings, attr):
     settings = dict(input_settings)
+    settings[VISIBLE_FOR_TESTING] = True
     settings["//command_line_option:build_python_zip"] = attr.build_python_zip
     if attr.bootstrap_impl:
         settings["//python/config_settings:bootstrap_impl"] = attr.bootstrap_impl
     if attr.extra_toolchains:
         settings["//command_line_option:extra_toolchains"] = attr.extra_toolchains
-    else:
-        settings["//command_line_option:extra_toolchains"] = input_settings["//command_line_option:extra_toolchains"]
+    if attr.python_version:
+        settings["//python/config_settings:python_version"] = attr.python_version
     return settings
 
 _perform_transition = transition(
@@ -37,11 +39,14 @@
     inputs = [
         "//python/config_settings:bootstrap_impl",
         "//command_line_option:extra_toolchains",
+        "//python/config_settings:python_version",
     ],
     outputs = [
         "//command_line_option:build_python_zip",
         "//command_line_option:extra_toolchains",
         "//python/config_settings:bootstrap_impl",
+        "//python/config_settings:python_version",
+        VISIBLE_FOR_TESTING,
     ],
 )
 
@@ -99,6 +104,7 @@
 toolchain.
 """,
         ),
+        "python_version": attr.string(),
         "target": attr.label(executable = True, cfg = "target"),
         "_allowlist_function_transition": attr.label(
             default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
@@ -125,7 +131,10 @@
     reconfig_kwargs = {}
     reconfig_kwargs["bootstrap_impl"] = kwargs.pop("bootstrap_impl", None)
     reconfig_kwargs["extra_toolchains"] = kwargs.pop("extra_toolchains", None)
+    reconfig_kwargs["python_version"] = kwargs.pop("python_version", None)
     reconfig_kwargs["env"] = kwargs.get("env")
+    reconfig_kwargs["target_compatible_with"] = kwargs.get("target_compatible_with")
+
     inner_name = "_{}_inner" + name
     _py_reconfig_test(
         name = name,
@@ -178,6 +187,7 @@
                 "short_path": runtime.interpreter.short_path if runtime.interpreter else None,
             },
             "interpreter_path": runtime.interpreter_path,
+            "toolchain_label": str(getattr(toolchain, "toolchain_label", None)),
         }),
     )
     return [DefaultInfo(
diff --git a/tests/toolchains/BUILD.bazel b/tests/toolchains/BUILD.bazel
index 2f804a4..c55dc92 100644
--- a/tests/toolchains/BUILD.bazel
+++ b/tests/toolchains/BUILD.bazel
@@ -12,9 +12,8 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-load(":defs.bzl", "acceptance_tests")
-load(":versions_test.bzl", "versions_test_suite")
+load(":defs.bzl", "define_toolchain_tests")
 
-versions_test_suite(name = "versions_test")
-
-acceptance_tests()
+define_toolchain_tests(
+    name = "toolchain_tests",
+)
diff --git a/tests/toolchains/defs.bzl b/tests/toolchains/defs.bzl
index 723272d..076e6b4 100644
--- a/tests/toolchains/defs.bzl
+++ b/tests/toolchains/defs.bzl
@@ -12,192 +12,40 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-"""This module contains the definition for the toolchains testing rules.
-"""
+""
 
 load("//python:versions.bzl", "PLATFORMS", "TOOL_VERSIONS")
-load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED")  # buildifier: disable=bzl-visibility
-load("//python/private:toolchain_types.bzl", "TARGET_TOOLCHAIN_TYPE")  # buildifier: disable=bzl-visibility
+load("//tests/support:sh_py_run_test.bzl", "py_reconfig_test")
 
-_WINDOWS_RUNNER_TEMPLATE = """\
-@ECHO OFF
-set PATHEXT=.COM;.EXE;.BAT
-powershell.exe -c "& ./{interpreter_path} {run_acceptance_test_py}"
-"""
+def define_toolchain_tests(name):
+    """Define the toolchain tests.
 
-def _acceptance_test_impl(ctx):
-    files = []
-
-    if BZLMOD_ENABLED:
-        module_bazel = ctx.actions.declare_file("/".join([ctx.attr.python_version, "MODULE.bazel"]))
-        ctx.actions.expand_template(
-            template = ctx.file._module_bazel_tmpl,
-            output = module_bazel,
-            substitutions = {"%python_version%": ctx.attr.python_version},
-        )
-        files.append(module_bazel)
-
-        workspace = ctx.actions.declare_file("/".join([ctx.attr.python_version, "WORKSPACE"]))
-        ctx.actions.write(workspace, "")
-        files.append(workspace)
-    else:
-        workspace = ctx.actions.declare_file("/".join([ctx.attr.python_version, "WORKSPACE"]))
-        ctx.actions.expand_template(
-            template = ctx.file._workspace_tmpl,
-            output = workspace,
-            substitutions = {"%python_version%": ctx.attr.python_version},
-        )
-        files.append(workspace)
-
-    build_bazel = ctx.actions.declare_file("/".join([ctx.attr.python_version, "BUILD.bazel"]))
-    ctx.actions.expand_template(
-        template = ctx.file._build_bazel_tmpl,
-        output = build_bazel,
-        substitutions = {"%python_version%": ctx.attr.python_version},
-    )
-    files.append(build_bazel)
-
-    python_version_test = ctx.actions.declare_file("/".join([ctx.attr.python_version, "python_version_test.py"]))
-    ctx.actions.symlink(
-        target_file = ctx.file._python_version_test,
-        output = python_version_test,
-    )
-    files.append(python_version_test)
-
-    run_acceptance_test_py = ctx.actions.declare_file("/".join([ctx.attr.python_version, "run_acceptance_test.py"]))
-    ctx.actions.expand_template(
-        template = ctx.file._run_acceptance_test_tmpl,
-        output = run_acceptance_test_py,
-        substitutions = {
-            "%is_bzlmod%": str(BZLMOD_ENABLED),
-            "%is_windows%": str(ctx.attr.is_windows),
-            "%python_version%": ctx.attr.python_version,
-            "%test_location%": "/".join([ctx.attr.test_location, ctx.attr.python_version]),
-        },
-    )
-    files.append(run_acceptance_test_py)
-
-    toolchain = ctx.toolchains[TARGET_TOOLCHAIN_TYPE]
-    py3_runtime = toolchain.py3_runtime
-    interpreter_path = py3_runtime.interpreter_path
-    if not interpreter_path:
-        interpreter_path = py3_runtime.interpreter.short_path
-
-    if ctx.attr.is_windows:
-        executable = ctx.actions.declare_file("run_test_{}.bat".format(ctx.attr.python_version))
-        ctx.actions.write(
-            output = executable,
-            content = _WINDOWS_RUNNER_TEMPLATE.format(
-                interpreter_path = interpreter_path.replace("../", "external/"),
-                run_acceptance_test_py = run_acceptance_test_py.short_path,
-            ),
-            is_executable = True,
-        )
-    else:
-        executable = ctx.actions.declare_file("run_test_{}.sh".format(ctx.attr.python_version))
-        ctx.actions.write(
-            output = executable,
-            content = "exec '{interpreter_path}' '{run_acceptance_test_py}'".format(
-                interpreter_path = interpreter_path,
-                run_acceptance_test_py = run_acceptance_test_py.short_path,
-            ),
-            is_executable = True,
-        )
-    files.append(executable)
-    files.extend(ctx.files._distribution)
-
-    return [DefaultInfo(
-        executable = executable,
-        files = depset(
-            direct = files,
-            transitive = [py3_runtime.files],
-        ),
-        runfiles = ctx.runfiles(
-            files = files,
-            transitive_files = py3_runtime.files,
-        ),
-    )]
-
-_acceptance_test = rule(
-    implementation = _acceptance_test_impl,
-    doc = "A rule for the toolchain acceptance tests.",
-    attrs = {
-        "is_windows": attr.bool(
-            doc = "(Provided by the macro) Whether this is running under Windows or not.",
-            mandatory = True,
-        ),
-        "python_version": attr.string(
-            doc = "The Python version to be used when requesting the toolchain.",
-            mandatory = True,
-        ),
-        "test_location": attr.string(
-            doc = "(Provided by the macro) The value of native.package_name().",
-            mandatory = True,
-        ),
-        "_build_bazel_tmpl": attr.label(
-            doc = "The BUILD.bazel template.",
-            allow_single_file = True,
-            default = Label("//tests/toolchains/workspace_template:BUILD.bazel.tmpl"),
-        ),
-        "_distribution": attr.label(
-            doc = "The rules_python source distribution.",
-            default = Label("//:distribution"),
-        ),
-        "_module_bazel_tmpl": attr.label(
-            doc = "The MODULE.bazel template.",
-            allow_single_file = True,
-            default = Label("//tests/toolchains/workspace_template:MODULE.bazel.tmpl"),
-        ),
-        "_python_version_test": attr.label(
-            doc = "The python_version_test.py used to test the Python version.",
-            allow_single_file = True,
-            default = Label("//tests/toolchains/workspace_template:python_version_test.py"),
-        ),
-        "_run_acceptance_test_tmpl": attr.label(
-            doc = "The run_acceptance_test.py template.",
-            allow_single_file = True,
-            default = Label("//tests/toolchains:run_acceptance_test.py.tmpl"),
-        ),
-        "_workspace_tmpl": attr.label(
-            doc = "The WORKSPACE template.",
-            allow_single_file = True,
-            default = Label("//tests/toolchains/workspace_template:WORKSPACE.tmpl"),
-        ),
-    },
-    test = True,
-    toolchains = [TARGET_TOOLCHAIN_TYPE],
-)
-
-def acceptance_test(python_version, **kwargs):
-    _acceptance_test(
-        is_windows = select({
-            "@bazel_tools//src/conditions:host_windows": True,
-            "//conditions:default": False,
-        }),
-        python_version = python_version,
-        test_location = native.package_name(),
-        **kwargs
-    )
-
-# buildifier: disable=unnamed-macro
-def acceptance_tests():
-    """Creates a matrix of acceptance_test targets for all the toolchains.
+    Args:
+        name: Only present to satisfy tooling.
     """
-    for python_version in TOOL_VERSIONS.keys():
-        for platform, meta in PLATFORMS.items():
-            if platform not in TOOL_VERSIONS[python_version]["sha256"]:
-                continue
-            acceptance_test(
-                name = "python_{python_version}_{platform}_test".format(
-                    python_version = python_version.replace(".", "_"),
-                    platform = platform,
-                ),
-                python_version = python_version,
-                target_compatible_with = meta.compatible_with,
-                tags = [
-                    "acceptance-test",
-                    # For some inexplicable reason, these fail locally with
-                    # sandboxing enabled, but not on CI.
-                    "no-sandbox",
-                ],
-            )
+    for platform_key, platform_info in PLATFORMS.items():
+        native.config_setting(
+            name = "_is_{}".format(platform_key),
+            constraint_values = platform_info.compatible_with,
+        )
+
+    for python_version, meta in TOOL_VERSIONS.items():
+        target_compatible_with = {
+            "//conditions:default": ["@platforms//:incompatible"],
+        }
+        for platform_key in meta["sha256"].keys():
+            is_platform = "_is_{}".format(platform_key)
+            target_compatible_with[is_platform] = []
+
+        py_reconfig_test(
+            name = "python_{}_test".format(python_version),
+            srcs = ["python_toolchain_test.py"],
+            main = "python_toolchain_test.py",
+            python_version = python_version,
+            env = {
+                "EXPECT_PYTHON_VERSION": python_version,
+            },
+            deps = ["//python/runfiles"],
+            data = ["//tests/support:current_build_settings"],
+            target_compatible_with = select(target_compatible_with),
+        )
diff --git a/tests/toolchains/python_toolchain_test.py b/tests/toolchains/python_toolchain_test.py
new file mode 100644
index 0000000..371b252
--- /dev/null
+++ b/tests/toolchains/python_toolchain_test.py
@@ -0,0 +1,28 @@
+import json
+import os
+import pathlib
+import sys
+import unittest
+
+from python.runfiles import runfiles
+
+
+class PythonToolchainTest(unittest.TestCase):
+    def test_expected_toolchain_matches(self):
+        expect_version = os.environ["EXPECT_PYTHON_VERSION"]
+
+        rf = runfiles.Create()
+        settings_path = rf.Rlocation(
+            "rules_python/tests/support/current_build_settings.json"
+        )
+        settings = json.loads(pathlib.Path(settings_path).read_text())
+
+        expected = "python_{}".format(expect_version.replace(".", "_"))
+        self.assertIn(expected, settings["toolchain_label"], str(settings))
+
+        actual = "{v.major}.{v.minor}.{v.micro}".format(v=sys.version_info)
+        self.assertEqual(actual, expect_version)
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/tests/toolchains/run_acceptance_test.py.tmpl b/tests/toolchains/run_acceptance_test.py.tmpl
deleted file mode 100644
index c52e078..0000000
--- a/tests/toolchains/run_acceptance_test.py.tmpl
+++ /dev/null
@@ -1,90 +0,0 @@
-# Copyright 2022 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import subprocess
-import unittest
-import pathlib
-
-class TestPythonVersion(unittest.TestCase):
-    @classmethod
-    def setUpClass(cls):
-        os.chdir("%test_location%")
-        test_srcdir = os.environ["TEST_SRCDIR"]
-        # When bzlmod is enabled, the name of the directory in runfiles changes
-        # to _main instead of rules_python
-        if os.path.exists(os.path.join(test_srcdir, "_main")):
-          rules_python_path = os.path.join(test_srcdir, "_main")
-        else:
-          rules_python_path = os.path.join(test_srcdir, "rules_python")
-
-        test_tmpdir = os.environ["TEST_TMPDIR"]
-        if %is_windows%:
-            home = os.path.join(test_tmpdir, "HOME")
-            os.mkdir(home)
-            os.environ["HOME"] = home
-
-            local_app_data = os.path.join(test_tmpdir, "LocalAppData")
-            os.mkdir(local_app_data)
-            os.environ["LocalAppData"] = local_app_data
-
-        # Bazelisk requires a cache directory be set
-        os.environ["XDG_CACHE_HOME"] = os.path.join(test_tmpdir, "xdg-cache-home")
-
-        # Unset this so this works when called by Bazel's latest Bazel build
-        # pipeline. It sets the following combination, which interfere with each other:
-        # * --sandbox_tmpfs_path=/tmp
-        # * --test_env=USE_BAZEL_VERSION
-        # * USE_BAZEL_VERSION=/tmp/<something>
-        os.environ.pop("USE_BAZEL_VERSION", None)
-
-        bazelrc_lines = [
-            "build --test_output=errors",
-        ]
-
-        if %is_bzlmod%:
-            bazelrc_lines.extend(
-                [
-                    'build --override_module rules_python="{}"'.format(
-                        rules_python_path.replace("\\", "/")
-                    ),
-                    "common --enable_bzlmod",
-                ]
-            )
-        else:
-            bazelrc_lines.extend(
-                [
-                    'build --override_repository rules_python="{}"'.format(
-                        rules_python_path.replace("\\", "/")
-                    ),
-                    "common --noexperimental_enable_bzlmod",
-                ]
-            )
-
-        bazelrc = pathlib.Path(".bazelrc")
-        bazelrc.write_text(os.linesep.join(bazelrc_lines))
-
-    def test_match_toolchain(self):
-        output = subprocess.check_output(
-            f"bazel run --announce_rc @python//:python3 -- --version",
-            shell = True, # Shell needed to look up via PATH
-            text=True,
-        ).strip()
-        self.assertEqual(output, "Python %python_version%")
-
-        subprocess.run("bazel test --announce_rc //...", shell=True, check=True)
-
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/tests/toolchains/versions_test.bzl b/tests/toolchains/versions_test.bzl
deleted file mode 100644
index b885d22..0000000
--- a/tests/toolchains/versions_test.bzl
+++ /dev/null
@@ -1,51 +0,0 @@
-# Copyright 2022 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-"""Unit tests for starlark helpers
-See https://docs.bazel.build/versions/main/skylark/testing.html#for-testing-starlark-utilities
-"""
-
-load("@bazel_skylib//lib:unittest.bzl", "asserts", "unittest")
-load("//python:versions.bzl", "MINOR_MAPPING", "TOOL_VERSIONS")
-
-required_platforms = [
-    "x86_64-apple-darwin",
-    "x86_64-unknown-linux-gnu",
-]
-
-def _smoke_test_impl(ctx):
-    env = unittest.begin(ctx)
-    for version in TOOL_VERSIONS.keys():
-        platforms = TOOL_VERSIONS[version]["sha256"]
-        for required_platform in required_platforms:
-            asserts.true(
-                env,
-                required_platform in platforms.keys(),
-                "Missing platform {} for version {}".format(required_platform, version),
-            )
-    for minor in MINOR_MAPPING:
-        version = MINOR_MAPPING[minor]
-        asserts.true(
-            env,
-            version in TOOL_VERSIONS.keys(),
-            "Missing version {} in TOOL_VERSIONS".format(version),
-        )
-    return unittest.end(env)
-
-# The unittest library requires that we export the test cases as named test rules,
-# but their names are arbitrary and don't appear anywhere.
-_t0_test = unittest.make(_smoke_test_impl)
-
-def versions_test_suite(name):
-    unittest.suite(name, _t0_test)
diff --git a/tests/toolchains/workspace_template/BUILD.bazel b/tests/toolchains/workspace_template/BUILD.bazel
deleted file mode 100644
index 7f3e7b0..0000000
--- a/tests/toolchains/workspace_template/BUILD.bazel
+++ /dev/null
@@ -1,6 +0,0 @@
-exports_files([
-    "BUILD.bazel.tmpl",
-    "MODULE.bazel.tmpl",
-    "WORKSPACE.tmpl",
-    "python_version_test.py",
-])
diff --git a/tests/toolchains/workspace_template/BUILD.bazel.tmpl b/tests/toolchains/workspace_template/BUILD.bazel.tmpl
deleted file mode 100644
index 4a45209..0000000
--- a/tests/toolchains/workspace_template/BUILD.bazel.tmpl
+++ /dev/null
@@ -1,9 +0,0 @@
-load("@rules_python//python:defs.bzl", "py_test")
-
-py_test(
-    name = "python_version_test",
-    srcs = ["python_version_test.py"],
-    env = {
-        "PYTHON_VERSION": "%python_version%",
-    },
-)
diff --git a/tests/toolchains/workspace_template/MODULE.bazel.tmpl b/tests/toolchains/workspace_template/MODULE.bazel.tmpl
deleted file mode 100644
index 9e3a844..0000000
--- a/tests/toolchains/workspace_template/MODULE.bazel.tmpl
+++ /dev/null
@@ -1,19 +0,0 @@
-module(
-    name = "module_test",
-    version = "0.0.0",
-    compatibility_level = 1,
-)
-
-bazel_dep(name = "bazel_skylib", version = "1.3.0")
-bazel_dep(name = "rules_python", version = "0.0.0")
-local_path_override(
-    module_name = "rules_python",
-    path = "",
-)
-
-python = use_extension("@rules_python//python/extensions:python.bzl", "python")
-python.toolchain(
-    is_default = True,
-    python_version = "%python_version%",
-)
-use_repo(python, "python_versions", python = "python_%python_version%".replace(".", "_"))
diff --git a/tests/toolchains/workspace_template/README.md b/tests/toolchains/workspace_template/README.md
deleted file mode 100644
index b4d6e6a..0000000
--- a/tests/toolchains/workspace_template/README.md
+++ /dev/null
@@ -1,4 +0,0 @@
-# Toolchains testing WORKSPACE template
-
-This directory contains templates for generating acceptance tests for the
-toolchains.
diff --git a/tests/toolchains/workspace_template/WORKSPACE.tmpl b/tests/toolchains/workspace_template/WORKSPACE.tmpl
deleted file mode 100644
index 3335f4b..0000000
--- a/tests/toolchains/workspace_template/WORKSPACE.tmpl
+++ /dev/null
@@ -1,41 +0,0 @@
-# Copyright 2022 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-workspace(name = "workspace_test")
-
-local_repository(
-    name = "rules_python",
-    path = "",
-)
-
-load("@rules_python//python:repositories.bzl", "python_register_toolchains", "py_repositories")
-
-py_repositories()
-
-python_register_toolchains(
-    name = "python",
-    python_version = "%python_version%",
-)
-
-load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
-http_archive(
-    name = "bazel_skylib",
-    urls = [
-        "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz",
-        "https://github.com/bazelbuild/bazel-skylib/releases/download/1.1.1/bazel-skylib-1.1.1.tar.gz",
-    ],
-    sha256 = "c6966ec828da198c5d9adbaa94c05e3a1c7f21bd012a0b29ba8ddbccb2c93b0d",
-)
-load("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
-bazel_skylib_workspace()
diff --git a/tests/toolchains/workspace_template/python_version_test.py b/tests/toolchains/workspace_template/python_version_test.py
deleted file mode 100644
index c82611c..0000000
--- a/tests/toolchains/workspace_template/python_version_test.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# Copyright 2022 The Bazel Authors. All rights reserved.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#    http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import os
-import platform
-import unittest
-
-
-class TestPythonVersion(unittest.TestCase):
-    def test_match_toolchain(self):
-        self.assertEqual(platform.python_version(), os.getenv("PYTHON_VERSION"))
-
-
-if __name__ == "__main__":
-    unittest.main()