Skip to content

Commit

Permalink
features for 0.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
kriscfoster committed Mar 4, 2024
1 parent faf78bc commit 68788b6
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 89 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@ services:
image: junit-image-test:test_container
entrypoint: ["/busybox/sh", "./test_container_entrypoint.sh"]
environment:
- JAVA_BINARY=/path/to/jdk/in/custom/image/bin/java
- JAVA_HOME=/path/to/jdk/in/custom/image/bin/java
- JUNIT_PARAMS=--include-classname com.something.integration.*
```

## Pre compose up script

Sometimes, you may need some logic to run before the compose test containers come up. You can use `pre_compose_up_script` for that purpose. See [examples/pre-compose-up-script-test](examples/pre-compose-up-script-test) for an example.
172 changes: 90 additions & 82 deletions docker_compose/docker_compose_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,29 +17,30 @@ load("@rules_pkg//:pkg.bzl", "pkg_tar")
load("@repo_absolute_path//:build_root.bzl", "BUILD_WORKSPACE_DIRECTORY")
load("@rules_oci//oci:defs.bzl", "oci_image", "oci_tarball")

common_tags = [
"docker", # these tests depend on docker
"exclusive", # these tests should run independent of others
"external", # test has an external dependency; disable test caching
]

def docker_compose_test(
name,
docker_compose_file,
docker_compose_test_container,
pre_compose_up_script = "",
local_image_targets = "",
data = [],
tags = [],
size = "large",
**kwargs):
tags = [
"external", # test has an external dependency; disable test caching
] + tags

tags = common_tags + tags
data = data + [ docker_compose_file ]
if len(pre_compose_up_script):
data = data + [ pre_compose_up_script ]
native.sh_test(
name = name,
srcs = ["@rules_docker_compose//docker_compose:docker_compose_test.sh"],
env = {
"WORKSPACE_PATH": BUILD_WORKSPACE_DIRECTORY,
"DOCKER_COMPOSE_FILE": "$(location " + docker_compose_file + ")",
"DOCKER_COMPOSE_TEST_CONTAINER": docker_compose_test_container,
"LOCAL_IMAGE_TARGETS": local_image_targets.replace(":", "/"),
},
env = _get_env(docker_compose_file, local_image_targets, docker_compose_test_container, pre_compose_up_script),
size = size,
tags = tags,
data = data,
Expand All @@ -51,6 +52,7 @@ def junit_docker_compose_test(
name,
docker_compose_file,
docker_compose_test_container,
pre_compose_up_script = "",
local_image_targets = "",
classpath_jars = [],
test_image_base = None,
Expand All @@ -60,86 +62,92 @@ def junit_docker_compose_test(
tags = [],
size = "large",
**kwargs):
tags = [
"external", # test has an external dependency; disable test caching
] + tags

tags = common_tags + tags
data = data + [ docker_compose_file ]
if len(pre_compose_up_script):
data = data + [ pre_compose_up_script ]

if test_image_base == None:
fail("if you are definiing test_srcs, you need to provide a test_image_base")

# building an uber jar with test srcs & all dependencies
native.java_binary(
name = name + "_uber_jar",
srcs = test_srcs,
testonly = True,
deps = test_deps,
resources = test_deps,
main_class = "not_used",
)

# uber jar contains test classes
pkg_tar(
name = name + "_uber_jar_tar",
srcs = [name + "_uber_jar_deploy.jar"],
testonly = True,
)

# these are jars that need to be on the classpath for the junit tests to execute
pkg_tar(
name = name + "_required_classpath_jars_tar",
srcs = classpath_jars,
testonly = True,
)

# this is what actually runs the junit jar for your test execution
pkg_tar(
name = name + "_test_container_entrypoint",
srcs = ["@rules_docker_compose//docker_compose:test_container_entrypoint.sh"],
)

# if there are srcs, build a test container that includes the tests
if len(test_srcs):

if test_image_base == None:
fail("if you are definiing test_srcs, you need to provide a test_image_base")

# building an uber jar with test srcs & all dependencies
native.java_binary(
name = name + "_uber_jar",
srcs = test_srcs,
testonly = True,
deps = test_deps,
main_class = "not_used",
)

# uber jar contains test classes
pkg_tar(
name = name + "_uber_jar_tar",
srcs = [name + "_uber_jar"],
testonly = True,
)

# these are jars that need to be on the classpath for the junit tests to execute
pkg_tar(
name = name + "_required_classpath_jars_tar",
srcs = classpath_jars,
testonly = True,
)

# this is what actually runs the junit jar for your test execution
pkg_tar(
name = name + "_test_container_entrypoint",
srcs = ["@rules_docker_compose//docker_compose:test_container_entrypoint.sh"],
)

oci_image(
name = "java_image",
base = test_image_base,
tars = [
name + "_uber_jar_tar",
name + "_required_classpath_jars_tar",
name + "_test_container_entrypoint",
],
testonly = True,
)

oci_tarball(
name = docker_compose_test_container,
image = ":java_image",
repo_tags = ["%s:%s" % (native.package_name(), docker_compose_test_container)],
testonly = True,
)

# this builds & installs the test image.
native.sh_binary(
name = name + "_integration_test_image_fixture",
srcs = [docker_compose_test_container],
testonly = True,
)

data.append(name + "_integration_test_image_fixture")
local_image_targets += "%s:%s" % (native.package_name(), docker_compose_test_container)
oci_image(
name = name.lower() + "_java_image",
base = test_image_base,
tars = [
name + "_uber_jar_tar",
name + "_required_classpath_jars_tar",
name + "_test_container_entrypoint",
],
testonly = True,
)

oci_tarball(
name = docker_compose_test_container,
image = name.lower() + "_java_image",
repo_tags = ["%s:%s" % (native.package_name(), docker_compose_test_container)],
testonly = True,
)

# this builds & installs the test image.
native.sh_binary(
name = name + "_integration_test_image_fixture",
srcs = [docker_compose_test_container],
testonly = True,
)

data.append(name + "_integration_test_image_fixture")
if len(local_image_targets):
local_image_targets += ","
local_image_targets += "%s:%s" % (native.package_name(), docker_compose_test_container)
native.sh_test(
name = name,
srcs = ["@rules_docker_compose//docker_compose:docker_compose_test.sh"],
env = {
"WORKSPACE_PATH": BUILD_WORKSPACE_DIRECTORY,
"DOCKER_COMPOSE_FILE": "$(location " + docker_compose_file + ")",
"DOCKER_COMPOSE_TEST_CONTAINER": docker_compose_test_container,
"LOCAL_IMAGE_TARGETS": local_image_targets.replace(":", "/"),
},
env = _get_env(docker_compose_file, local_image_targets, docker_compose_test_container, pre_compose_up_script),
size = size,
tags = tags,
data = data,
**kwargs,
)


def _get_env(docker_compose_file, local_image_targets, docker_compose_test_container, pre_compose_up_script):
env = {
"WORKSPACE_PATH": BUILD_WORKSPACE_DIRECTORY,
"DOCKER_COMPOSE_FILE": "$(location " + docker_compose_file + ")",
"LOCAL_IMAGE_TARGETS": local_image_targets.replace(":", "/"),
"DOCKER_COMPOSE_TEST_CONTAINER": docker_compose_test_container,
}

if len(pre_compose_up_script):
env["PRE_COMPOSE_UP_SCRIPT"] = "$(location " + pre_compose_up_script + ")"
return env
15 changes: 15 additions & 0 deletions docker_compose/docker_compose_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.

# we should not use "set -e" here because we want the docker-compose down to happen at the end regardless of failure/success.

# start by building any local images that are needed for the docker-compose tests
export IFS=","
echo $LOCAL_IMAGE_TARGETS
for LOCAL_IMAGE_TARGET in $LOCAL_IMAGE_TARGETS; do
s="$LOCAL_IMAGE_TARGET.sh"
echo "building $LOCAL_IMAGE_TARGET with $s"
$s
done

# PRE_COMPOSE_UP_SCRIPT is set
if [[ -n "$PRE_COMPOSE_UP_SCRIPT" ]]; then
# we want to move to the location of the script before executing it
# so paths are relative to it. After the script is executed, we move
# back to the original location.
location=$(pwd)
cd $WORKSPACE_PATH
cd $(dirname $PRE_COMPOSE_UP_SCRIPT)
$(basename $PRE_COMPOSE_UP_SCRIPT)
cd $location
fi

# we need to use the path of the real compose file in the file-tree.
# if we use the file from inside the sandbox, symlinks will be used for volume mounted files.
ABSOLUTE_COMPOSE_FILE_PATH=$WORKSPACE_PATH/$DOCKER_COMPOSE_FILE
Expand Down
15 changes: 9 additions & 6 deletions docker_compose/test_container_entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,25 @@
# See the License for the specific language governing permissions and
# limitations under the License.

if [[ -z "$JAVA_BINARY" ]]; then
JAVA_BINARY="/usr/bin/java"
if [[ -z "$JAVA_HOME" ]]; then
JAVA_HOME="/usr"
fi

TEST_UBER_JAR=$(find ./ -maxdepth 1 -name '*_uber_jar.jar')
TEST_UBER_JAR=$(find ./ -maxdepth 1 -name '*_uber_jar_deploy.jar')
JUNIT_PLATFORM_CONSOLE_STANDALONE_JAR=$(find ./ -maxdepth 1 -name '*junit-platform-console-standalone*.jar')

# TODO: need to find a better solution than adding all of the jars to the class-path below
# The only one we should need to add is the fat jar because it should contain the rest of them..
# However, it seems like we need to add all of the spring/spring-boot jars like this.
JARS=$(find ./ -maxdepth 1 -name '*.jar')
JARS=$(find ./ -maxdepth 1 -name '*.jar' ! -name '*_uber_jar_deploy.jar')
CLASS_PATH_STRING=""
for JAR in $JARS; do
CLASS_PATH_STRING="$CLASS_PATH_STRING --class-path $JAR"
done

# JUNIT_PARAMS can be set in their compose file to filter for specific tests
# JUNIT_PARAMS can be set in the docker-compose file to filter for specific tests
# e.g. --include-classname com.something.integration.*
$JAVA_BINARY -jar $JUNIT_PLATFORM_CONSOLE_STANDALONE_JAR --class-path $TEST_UBER_JAR --scan-class-path --fail-if-no-tests $CLASS_PATH_STRING $JUNIT_PARAMS
cmd="$JAVA_HOME/bin/java -jar $JUNIT_PLATFORM_CONSOLE_STANDALONE_JAR \
--scan-class-path --fail-if-no-tests $CLASS_PATH_STRING --class-path $TEST_UBER_JAR $JUNIT_PARAMS"
echo $cmd
$cmd
23 changes: 23 additions & 0 deletions examples/pre-compose-up-script-test/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Copyright (c) 2023, Salesforce, Inc.
# SPDX-License-Identifier: Apache-2

# 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("@rules_docker_compose//docker_compose:docker_compose_test.bzl", "docker_compose_test")

docker_compose_test(
name = "pre-compose-up-script-test",
docker_compose_file = ":docker-compose.yml",
docker_compose_test_container = "test_container",
pre_compose_up_script = ":src/test/resources/setup_test.sh"
)
21 changes: 21 additions & 0 deletions examples/pre-compose-up-script-test/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright (c) 2023, Salesforce, Inc.
# SPDX-License-Identifier: Apache-2

# 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.

services:
test_container:
image: gcr.io/distroless/static-debian12:debug
entrypoint: ["cat", "/resources/generated_file.txt"]
volumes:
- ./src/test/resources:/resources
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# we don't want to check-in the generated file
# because that's what we're actually testing here
# (that the file is generated when the test is executed).
generated_file.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
set -e

# This file is created as a pre-req to the docker-compose test actually running.
# Locally, the file will always be there but it won't be checked in as it is in .gitignore.
# CI will make sure that the file is generated on every execution.
touch generated_file.txt

0 comments on commit 68788b6

Please sign in to comment.