1# Rules for running robolectric tests.
2#
3# Uses the following variables:
4#
5#   LOCAL_JAVA_LIBRARIES
6#   LOCAL_STATIC_JAVA_LIBRARIES
7#   LOCAL_ROBOTEST_FAILURE_FATAL
8#   LOCAL_ROBOTEST_TIMEOUT
9#   LOCAL_TEST_PACKAGE
10#   LOCAL_ROBOTEST_FILES
11#   ROBOTEST_FAILURE_FATAL
12#   ROBOTEST_FILTER
13#   ROBOTEST_RUN_INDIVIDUALLY
14#
15#
16# If ROBOTEST_FAILURE_FATAL is set to true then failing tests will cause a
17# build failure. Otherwise failures will be logged but ignored by make.
18#
19# If ROBOTEST_FILTER is set to a regex then only tests matching that pattern
20# will be run. This currently only works at the class level.
21#
22# TODO: Switch to a JUnit runner which can support method-level test
23# filtering and use that rather than grep to implement ROBOTEST_FILTER.
24#
25# If ROBOTEST_RUN_INDIVIDUALLY is set to true, each test class will be run by a
26# different JVM, preventing any interaction between different tests. This is
27# significantly slower than running all tests within the same JVM, but prevents
28# unwanted interactions.
29#
30# Tests classes are found by looking for *Test.java files in
31# LOCAL_PATH recursively.
32
33################################################
34# General settings, independent of the module. #
35################################################
36
37### Used for running tests.
38
39# Where to find Robolectric.
40my_robolectric_script_path := $(call my-dir)
41# Explicitly define the jars and their classpath ordering.
42include $(my_robolectric_script_path)/classpath_jars.mk
43my_robolectric_jars := \
44    $(addprefix $(my_robolectric_script_path)/,$(my_robolectric_runtime_deps)) \
45    $(call java-lib-files,junit)
46
47my_collect_target := $(LOCAL_MODULE)-coverage
48my_report_target := $(LOCAL_MODULE)-jacoco
49# Whether or not to ignore the result of running the robotests.
50# LOCAL_ROBOTEST_FAILURE_FATAL will take precedence over ROBOTEST_FAILURE_FATAL,
51# if present.
52my_failure_fatal := $(if $(LOCAL_ROBOTEST_FAILURE_FATAL)$(ROBOTEST_FAILURE_FATAL),true,false)
53# The timeout for the command. A value of '0' means no timeout. The default is
54# 10 minutes.
55my_timeout := $(if $(LOCAL_ROBOTEST_TIMEOUT),$(LOCAL_ROBOTEST_TIMEOUT),600)
56# Command to filter the list of test classes.
57# If not specified, defaults to including all the tests.
58my_test_filter_command := $(if $(ROBOTEST_FILTER),grep -E "$(ROBOTEST_FILTER)",cat)
59
60# The directory containing the sources.
61my_instrument_makefile_dir := $(dir $(ALL_MODULES.$(LOCAL_TEST_PACKAGE).MAKEFILE))
62my_instrument_source_dirs := $(if $(LOCAL_INSTRUMENT_SOURCE_DIRS),\
63    $(LOCAL_INSTRUMENT_SOURCE_DIRS),\
64    $(my_instrument_makefile_dir)src $(my_instrument_makefile_dir)java)
65
66##########################
67# Used by base_rules.mk. #
68##########################
69
70LOCAL_MODULE_CLASS := FAKE
71# This is actually a phony target that is never built.
72LOCAL_BUILT_MODULE_STEM := test.fake
73# Since it is not built, it cannot be installed. But we will define our own
74# dist files, depending on which of the specific targets is invoked.
75LOCAL_UNINSTALLABLE_MODULE := true
76# Do not build it for checkbuild or mma
77LOCAL_DONT_CHECK_MODULE := true
78
79include $(BUILD_SYSTEM)/base_rules.mk
80
81
82#############################
83# Module specific settings. #
84#############################
85
86### Used for running tests.
87
88# The list of test classes. Robolectric requires an explicit list of tests to
89# run, which is compiled from the Java files ending in "Test" within the
90# directory from which this module is invoked.
91ifeq ($(strip $(LOCAL_ROBOTEST_FILES)),)
92    LOCAL_ROBOTEST_FILES := $(call find-files-in-subdirs,$(LOCAL_PATH)/src,*Test.java,.)
93endif
94# Convert the paths into package names by removing .java extension and replacing "/" with "."
95my_tests := $(subst /,.,$(basename $(LOCAL_ROBOTEST_FILES)))
96my_tests := $(sort $(shell echo '$(my_tests)' | tr ' ' '\n' | $(my_test_filter_command)))
97# The source jars containing the tests.
98my_srcs_jars := \
99    $(foreach lib, \
100        $(LOCAL_JAVA_LIBRARIES) $(LOCAL_STATIC_JAVA_LIBRARIES), \
101        $(call intermediates-dir-for,JAVA_LIBRARIES,$(lib),,COMMON)/classes-pre-proguard.jar) \
102    $(foreach lib, \
103        $(LOCAL_TEST_PACKAGE), \
104        $(call intermediates-dir-for,APPS,$(lib),,COMMON)/classes-pre-proguard.jar)
105# The jars needed to run the tests.
106my_jars := \
107    $(my_robolectric_jars) \
108    prebuilts/sdk/$(LOCAL_SDK_VERSION)/android.jar \
109    $(call java-lib-files,junitxml) \
110    $(my_srcs_jars)
111
112
113
114# Run tests.
115my_target := $(LOCAL_BUILT_MODULE)
116my_filename_stem := test
117
118android_all_lib_path := $(my_robolectric_script_path)/../android-all
119my_robolectric_path := $(intermediates.COMMON)/android-all
120android_all_jars := $(call find-files-in-subdirs,$(android_all_lib_path),*.jar,.)
121copy_android_all_jars := $(foreach j,$(android_all_jars),\
122    $(android_all_lib_path)/$(j):$(my_robolectric_path)/$(j))
123$(my_robolectric_path): $(call copy-many-files,$(copy_android_all_jars))
124$(my_target): $(my_robolectric_path)
125
126# Setting the DEBUG_ROBOLECTRIC environment variable will print additional logging from
127# Robolectric and also make it wait for a debugger to be connected.
128# For Android Studio / IntelliJ the debugger can be connected via the "remote" configuration:
129#     https://www.jetbrains.com/help/idea/2016.2/run-debug-configuration-remote.html
130# From command line the debugger can be connected via
131#     jdb -attach localhost:5005
132ifdef DEBUG_ROBOLECTRIC
133    # The arguments to the JVM needed to debug the tests.
134    # - server: wait for connection rather than connecting to a debugger
135    # - transport: how to accept debugger connections (sockets)
136    # - address: the port on which to accept debugger connections
137    # - timeout: how long (in ms) to wait for a debugger to connect
138    # - suspend: do not start running any code until the debugger connects
139    my_java_args := \
140        -Drobolectric.logging.enabled=true \
141        -Xdebug -agentlib:jdwp=server=y,transport=dt_socket,address=5005,suspend=y
142
143    # Remove the timeout so Robolectric doesn't get killed while debugging
144    my_timeout := 0
145endif
146
147include $(my_robolectric_script_path)/robotest-internal.mk
148# clean local variables
149my_java_args :=
150my_target :=
151
152# Target for running robolectric tests using jacoco
153my_target := $(LOCAL_BUILT_MODULE)-coverage
154my_filename_stem := coverage
155$(my_collect_target): $(my_target)
156$(my_target): $(call java-lib-files,jvm-jacoco-agent,true) $(my_robolectric_path)
157
158my_coverage_dir := $(intermediates)/coverage
159my_coverage_file := $(my_coverage_dir)/jacoco.exec
160
161# List of packages to exclude jacoco from running
162my_jacoco_excludes := \
163    org.robolectric.*:org.mockito.*:org.junit.*:org.objectweb.*:com.thoughtworks.xstream.*
164# The Jacoco agent JAR.
165my_jacoco_agent_jar := $(call java-lib-files,jvm-jacoco-agent,true)
166my_java_args := \
167    -javaagent:$(my_jacoco_agent_jar)=destfile=$(my_coverage_file),excludes=$(my_jacoco_excludes)
168include $(my_robolectric_script_path)/robotest-internal.mk
169# Clear temporary variables
170my_failure_fatal :=
171my_jacoco_agent_jar :=
172my_jacoco_excludes :=
173my_java_args :=
174my_robolectric_jars :=
175my_target :=
176my_tests :=
177my_filename_stem :=
178
179# Target for generating code coverage reports using jacoco.exec
180my_target := $(LOCAL_BUILT_MODULE)-jacoco
181$(my_report_target): $(my_target)
182
183# The JAR file containing the report generation tool.
184my_coverage_report_class := com.google.android.jacoco.reporter.ReportGenerator
185my_coverage_report_jar := $(call java-lib-files,jvm-jacoco-reporter,true)
186my_coverage_srcs_jars := $(my_srcs_jars)
187my_coverage_report_dist_file := $(my_report_target)-html.zip
188
189## jacoco code coverage reports
190include $(my_robolectric_script_path)/report-internal.mk
191# Clear temporary variables
192my_coverage_dir :=
193my_coverage_file :=
194my_coverage_report_class :=
195my_coverage_report_dist_file :=
196my_coverage_report_jar :=
197my_coverage_srcs_jars :=
198my_robolectric_script_path :=
199my_robolectric_path :=
200my_srcs_jars :=
201my_target :=
202
203# Clear local variables specific to this build.
204LOCAL_ROBOTEST_FAILURE_FATAL :=
205LOCAL_ROBOTEST_TIMEOUT :=
206LOCAL_ROBOTEST_FILES :=
207LOCAL_INSTRUMENT_SOURCE_DIRS :=
208