test(gazelle): have a go_test target for each gazelle test (#1537)

This provides better caching and it allows us to have better
developer velocity whilst iterating on a single test case and
it also solves some of the `timeout` errors I was seeing locally
because now each `gazelle` invocation is run at a lower
parallelism that `bazel` decides itself.
diff --git a/gazelle/python/BUILD.bazel b/gazelle/python/BUILD.bazel
index 507d69e..e993a14 100644
--- a/gazelle/python/BUILD.bazel
+++ b/gazelle/python/BUILD.bazel
@@ -1,6 +1,7 @@
 load("@bazel_gazelle//:def.bzl", "gazelle_binary")
-load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
 load("@rules_python//python:defs.bzl", "py_binary")
+load(":gazelle_test.bzl", "gazelle_test")
 
 go_library(
     name = "python",
@@ -53,13 +54,21 @@
     output_group = "python_zip_file",
 )
 
-go_test(
+gazelle_test(
     name = "python_test",
     srcs = ["python_test.go"],
     data = [
         ":gazelle_binary",
         ":helper",
-    ] + glob(["testdata/**"]),
+    ],
+    test_dirs = glob(
+        # Use this so that we don't need to manually maintain the list.
+        ["testdata/*"],
+        exclude = ["testdata/*.md"],
+        # The directories aren't inputs themselves; we just want their
+        # names.
+        exclude_directories = 0,
+    ),
     deps = [
         "@bazel_gazelle//testtools:go_default_library",
         "@com_github_ghodss_yaml//:yaml",
diff --git a/gazelle/python/gazelle_test.bzl b/gazelle/python/gazelle_test.bzl
new file mode 100644
index 0000000..7c0c242
--- /dev/null
+++ b/gazelle/python/gazelle_test.bzl
@@ -0,0 +1,49 @@
+# Copyright 2023 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.
+
+""
+
+load("@io_bazel_rules_go//go:def.bzl", "go_test")
+
+def gazelle_test(*, name, test_dirs, **kwargs):
+    """A simple macro to better cache gazelle integration tests
+
+    Args:
+        name (str): The name of the test suite target to be created and
+            the prefix to all of the individual test targets.
+        test_dirs (list[str]): The list of dirs in the 'testdata'
+            directory that we should create separate 'go_test' cases for.
+            Each of them will be prefixed with '{name}'.
+        **kwargs: extra arguments passed to 'go_test'.
+    """
+    tests = []
+
+    data = kwargs.pop("data", [])
+
+    for dir in test_dirs:
+        _, _, basename = dir.rpartition("/")
+
+        test = "{}_{}".format(name, basename)
+        tests.append(test)
+
+        go_test(
+            name = test,
+            data = native.glob(["{}/**".format(dir)]) + data,
+            **kwargs
+        )
+
+    native.test_suite(
+        name = name,
+        tests = tests,
+    )