-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
kotlin: Adding bazel macro for more convenient test target decla… (#221)
Creating test targets for Kotlin is a bit tedious. This change is to help alleviate that. Some callouts: 1. This will *only* run tests within the `io.envoyproxy.envoymobile` package space 2. This will fail if there are no tests in the provided test target I feel these are reasonable requirements for this project and can rely on this for the near future (we can revisit when we there is a solution which is more official). Bazel out of the box: ``` load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_test") kt_jvm_test( name = "example_kotlin_test", test_target = "com.example.myproject.mymodule.ExampleTest" srcs = [ "ExampleTest.kt", ], deps = [ "//:another_target", "@maven//:org_assertj_assertj_core", "@maven//:junit_junit", ] ) ``` With this change: ``` load("//bazel:kotlin_test.bzl", "envoy_mobile_kt_test) envoy_mobile_kt_test( name = "example_kotlin_test", srcs = [ "ExampleTest.kt", ], deps = [ "//:another_target", ] ) ``` Took this solution from: https://stackoverflow.com/questions/46365464/how-to-run-all-tests-in-bazel-from-a-single-java-test-rule For an explanation of how to fill out the fields, please see the relevant section in [PULL_REQUESTS.md](https://github.com/envoyproxy/envoy/blob/master/PULL_REQUESTS.md) Description: Adding bazel macro for more convenient test target declaration Risk Level: low Testing: locally Docs Changes: n/a Release Notes: [Optional Fixes #Issue] [Optional Deprecated:] Signed-off-by: JP Simard <[email protected]>
- Loading branch information
Showing
4 changed files
with
129 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,17 @@ | ||
licenses(["notice"]) # Apache 2 | ||
|
||
load("@envoy//bazel:envoy_build_system.bzl", "envoy_package") | ||
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_library") | ||
|
||
envoy_package() | ||
|
||
kt_jvm_library( | ||
name = "envoy_mobile_test_suite", | ||
srcs = [ | ||
"EnvoyMobileTestSuite.kt", | ||
], | ||
visibility = ["//visibility:public"], | ||
deps = [ | ||
"@maven//:junit_junit", | ||
], | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package io.envoyproxy.envoymobile.bazel | ||
|
||
import junit.framework.JUnit4TestAdapter | ||
import junit.framework.TestSuite | ||
import org.junit.runner.RunWith | ||
import java.io.File | ||
import java.lang.RuntimeException | ||
import java.net.URLClassLoader | ||
import java.util.zip.ZipFile | ||
|
||
/** | ||
* This is class is taken from https://stackoverflow.com/questions/46365464/how-to-run-all-tests-in-bazel-from-a-single-java-test-rule | ||
* | ||
* Translated to Kotlin and slightly modified | ||
* | ||
* Requirements: | ||
* 1. This only allows tests to be run if the package is within `io.envoyproxy.envoymobile` | ||
* 2. This requires at least one test to be defined in the test target | ||
*/ | ||
@RunWith(org.junit.runners.AllTests::class) | ||
object EnvoyMobileTestSuite { | ||
private const val CLASS_SUFFIX = ".class" | ||
private const val ENVOY_MOBILE_PACKAGE = "io.envoyproxy.envoymobile" | ||
|
||
@JvmStatic | ||
fun suite(): TestSuite { | ||
val suite = TestSuite() | ||
val classLoader = Thread.currentThread().contextClassLoader as URLClassLoader | ||
|
||
val testAdapters = mutableListOf<JUnit4TestAdapter>() | ||
// The first entry on the classpath contains the srcs from java_test | ||
val classesInJar = findClassesInJar(File(classLoader.urLs[0].path)) | ||
for (clazz in classesInJar) { | ||
val name = Class.forName(clazz) | ||
val testAdapter = JUnit4TestAdapter(name) | ||
testAdapters.add(testAdapter) | ||
} | ||
|
||
if (testAdapters.isEmpty()) { | ||
throw RuntimeException("Unable to find any tests in test target") | ||
} | ||
|
||
for (testAdapter in testAdapters) { | ||
suite.addTest(testAdapter) | ||
} | ||
return suite | ||
} | ||
|
||
private fun findClassesInJar(jarFile: File): Set<String> { | ||
val classNames = mutableSetOf<String>() | ||
|
||
ZipFile(jarFile).use { zipFile -> | ||
val entries = zipFile.entries() | ||
for (entry in entries) { | ||
val entryName = entry.name | ||
|
||
if (entryName.endsWith(CLASS_SUFFIX)) { | ||
val classNameEnd = entryName.length - CLASS_SUFFIX.length | ||
val resolvedClass = entryName.substring(0, classNameEnd).replace('/', '.') | ||
if (resolvedClass.contains(ENVOY_MOBILE_PACKAGE)) { | ||
classNames.add(resolvedClass) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return classNames | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
load("@io_bazel_rules_kotlin//kotlin:kotlin.bzl", "kt_jvm_test") | ||
|
||
# A basic macro to make it easier to declare and run kotlin tests | ||
# | ||
# Ergonomic improvements include: | ||
# 1. Avoiding the need to declare the test_class which requires a fully qualified class name (example below) | ||
# 2. Avoiding the need to redeclare common unit testing dependencies like JUnit | ||
# 3. Ability to run more than one test file per target | ||
# | ||
# Usage example: | ||
# load("//bazel:kotlin_test.bzl", "envoy_mobile_kt_test) | ||
# | ||
# envoy_mobile_kt_test( | ||
# name = "example_kotlin_test", | ||
# srcs = [ | ||
# "ExampleTest.kt", | ||
# ], | ||
# ) | ||
# | ||
def envoy_mobile_kt_test(name, srcs, deps = []): | ||
kt_jvm_test( | ||
name = name, | ||
test_class = "io.envoyproxy.envoymobile.bazel.EnvoyMobileTestSuite", | ||
srcs = srcs, | ||
deps = deps + [ | ||
"//bazel:envoy_mobile_test_suite", | ||
"@maven//:org_assertj_assertj_core", | ||
"@maven//:junit_junit", | ||
], | ||
) |