TestExecutor.java
/*
* Copyright (C) 2015 The Android Open Source Project
*
* 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.
*/
package androidx.test.internal.runner;
import android.app.Instrumentation;
import android.os.Bundle;
import android.util.Log;
import androidx.test.internal.runner.listener.InstrumentationRunListener;
import androidx.test.internal.util.Checks;
import androidx.tracing.Trace;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.junit.runner.JUnitCore;
import org.junit.runner.Request;
import org.junit.runner.Result;
import org.junit.runner.notification.RunListener;
/**
* Class that given a Request containing tests to run, wires up the test listeners and actually
* executes the test using upstream JUnit
*/
public final class TestExecutor {
private static final String LOG_TAG = "TestExecutor";
private final List<RunListener> listeners;
private final Instrumentation instr;
private TestExecutor(Builder builder) {
listeners = Checks.checkNotNull(builder.listeners);
instr = builder.instr;
}
/**
* Execute the tests and report the test results.
*
* <p>If an error occurred during the test execution, the exception will be thrown, and it's the
* caller's responsibility to handle the exception properly.
*/
public Bundle execute(Request request) throws UnsupportedEncodingException {
Trace.beginSection("execute tests");
try {
return execute(new JUnitCore(), request);
} finally {
Trace.endSection();
}
}
Bundle execute(JUnitCore junitRunner, Request request) throws UnsupportedEncodingException {
Bundle resultBundle = new Bundle();
setUpListeners(junitRunner);
Result junitResults = junitRunner.run(request);
ByteArrayOutputStream summaryStream = new ByteArrayOutputStream();
// create the stream used to output summary data to the user
try (PrintStream summaryWriter = new PrintStream(summaryStream)) {
reportRunEnded(listeners, summaryWriter, resultBundle, junitResults);
}
resultBundle.putString(
Instrumentation.REPORT_KEY_STREAMRESULT,
String.format("\n%s", summaryStream.toString("UTF_8")));
return resultBundle;
}
/** Initialize listeners and add them to the JUnitCore runner */
private void setUpListeners(JUnitCore testRunner) {
for (RunListener listener : listeners) {
Log.d(LOG_TAG, "Adding listener " + listener.getClass().getName());
testRunner.addListener(listener);
if (listener instanceof InstrumentationRunListener) {
((InstrumentationRunListener) listener).setInstrumentation(instr);
}
}
}
private void reportRunEnded(
List<RunListener> listeners,
PrintStream summaryWriter,
Bundle resultBundle,
Result jUnitResults) {
for (RunListener listener : listeners) {
if (listener instanceof InstrumentationRunListener) {
((InstrumentationRunListener) listener)
.instrumentationRunFinished(summaryWriter, resultBundle, jUnitResults);
}
}
}
public static class Builder {
private final List<RunListener> listeners = new ArrayList<RunListener>();
private final Instrumentation instr;
public Builder(Instrumentation instr) {
this.instr = instr;
}
/**
* Adds a custom RunListener
*
* @param listener the listener to add
* @return the {@link androidx.test.internal.runner.TestExecutor.Builder}
*/
public Builder addRunListener(RunListener listener) {
listeners.add(listener);
return this;
}
public TestExecutor build() {
return new TestExecutor(this);
}
}
}