Skip to content

Commit

Permalink
kotlin: Adding bazel macro for more convenient test target decla… (#221)
Browse files Browse the repository at this point in the history
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 <jp@jpsim.com>
  • Loading branch information
Alan Chiu authored and jpsim committed Nov 28, 2022
1 parent 2be3d8d commit 15db586
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 0 deletions.
14 changes: 14 additions & 0 deletions mobile/WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,20 @@ git_repository(
shallow_since = "1552938175 -0400",
)

load("@rules_jvm_external//:defs.bzl", "maven_install")

maven_install(
artifacts = [
# Test artifacts
"org.assertj:assertj-core:3.9.0",
"junit:junit:4.12"
],
repositories = [
"https://repo1.maven.org/maven2",
"https://jcenter.bintray.com/",
]
)

# Bazel Kotlin 1.3 patch: https://github.com/bazelbuild/rules_kotlin/issues/159
# bazelbuild/rules_kotlin currently doesn't work with Kotlin 1.3
# TODO: https://github.com/lyft/envoy-mobile/issues/68
Expand Down
16 changes: 16 additions & 0 deletions mobile/bazel/BUILD
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",
],
)
69 changes: 69 additions & 0 deletions mobile/bazel/EnvoyMobileTestSuite.kt
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
}
}
30 changes: 30 additions & 0 deletions mobile/bazel/kotlin_test.bzl
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",
],
)

0 comments on commit 15db586

Please sign in to comment.