1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16package android.support.test.runner; 17 18import android.content.Context; 19import android.os.Bundle; 20import android.os.Handler; 21import android.os.Looper; 22import android.os.Message; 23import android.support.test.internal.runner.TestRequestBuilder; 24 25import junit.framework.Assert; 26 27import org.junit.Before; 28import org.junit.Rule; 29import org.junit.Test; 30import org.junit.rules.TemporaryFolder; 31import org.mockito.Mock; 32import org.mockito.Mockito; 33import org.mockito.MockitoAnnotations; 34 35 36import java.io.BufferedWriter; 37import java.io.ByteArrayOutputStream; 38import java.io.File; 39import java.io.FileWriter; 40import java.io.IOException; 41import java.io.PrintStream; 42 43/** 44 * Unit tests for {@link AndroidJUnitRunner}. 45 */ 46public class AndroidJUnitRunnerTest { 47 public static final int SLEEP_TIME = 300; 48 49 private final Thread mInstantiationThread = Thread.currentThread(); 50 51 private AndroidJUnitRunner mAndroidJUnitRunner; 52 private PrintStream mStubStream; 53 @Mock 54 private TestRequestBuilder mMockBuilder; 55 @Mock 56 private Context mMockContext; 57 58 @Before 59 public void setUp() throws Exception { 60 mAndroidJUnitRunner = new AndroidJUnitRunner() { 61 62 @Override 63 TestRequestBuilder createTestRequestBuilder(PrintStream writer, 64 String... packageCodePaths) { 65 return mMockBuilder; 66 } 67 68 @Override 69 public Context getContext() { 70 return mMockContext; 71 } 72 }; 73 mAndroidJUnitRunner.setArguments(new Bundle()); 74 mStubStream = new PrintStream(new ByteArrayOutputStream()); 75 MockitoAnnotations.initMocks(this); 76 } 77 78 /** 79 * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when 80 * a single class name is provided. 81 */ 82 @Test 83 public void testBuildRequest_singleClass() { 84 Bundle b = new Bundle(); 85 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName"); 86 mAndroidJUnitRunner.buildRequest(b, mStubStream); 87 Mockito.verify(mMockBuilder).addTestClass("ClassName"); 88 } 89 90 /** 91 * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when 92 * multiple class names are provided. 93 */ 94 @Test 95 public void testBuildRequest_multiClass() { 96 Bundle b = new Bundle(); 97 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1,ClassName2"); 98 mAndroidJUnitRunner.buildRequest(b, mStubStream); 99 Mockito.verify(mMockBuilder).addTestClass("ClassName1"); 100 Mockito.verify(mMockBuilder).addTestClass("ClassName2"); 101 } 102 103 /** 104 * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when 105 * class name and method name is provided. 106 */ 107 @Test 108 public void testBuildRequest_method() { 109 Bundle b = new Bundle(); 110 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1#method"); 111 mAndroidJUnitRunner.buildRequest(b, mStubStream); 112 Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method"); 113 } 114 115 /** 116 * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when 117 * class name and method name is provided along with an additional class name. 118 */ 119 @Test 120 public void testBuildRequest_classAndMethodCombo() { 121 Bundle b = new Bundle(); 122 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1#method,ClassName2"); 123 mAndroidJUnitRunner.buildRequest(b, mStubStream); 124 Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method"); 125 Mockito.verify(mMockBuilder).addTestClass("ClassName2"); 126 } 127 128 /** 129 * Temp file used for testing 130 */ 131 @Rule 132 public TemporaryFolder mTmpFolder = new TemporaryFolder(); 133 134 /** 135 * Test {@link AndroidJUnitRunner#buildRequest(Bundle, PrintStream)} when 136 * multiple class and method names are provided within a test file 137 */ 138 @Test 139 public void testBuildRequest_testFile() throws IOException { 140 final File file = mTmpFolder.newFile("myTestFile.txt"); 141 BufferedWriter out = new BufferedWriter(new FileWriter(file)); 142 out.write("ClassName3\n"); 143 out.write("ClassName4#method2\n"); 144 out.close(); 145 146 Bundle b = new Bundle(); 147 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_FILE, file.getPath()); 148 b.putString(AndroidJUnitRunner.ARGUMENT_TEST_CLASS, "ClassName1#method1,ClassName2"); 149 mAndroidJUnitRunner.buildRequest(b, mStubStream); 150 Mockito.verify(mMockBuilder).addTestMethod("ClassName1", "method1"); 151 Mockito.verify(mMockBuilder).addTestClass("ClassName2"); 152 Mockito.verify(mMockBuilder).addTestClass("ClassName3"); 153 Mockito.verify(mMockBuilder).addTestMethod("ClassName4", "method2"); 154 } 155 156 /** 157 * Ensures that the main looper is not blocked and can process 158 * messages during test execution. 159 */ 160 @Test 161 public void testMainLooperIsAlive() throws InterruptedException { 162 final boolean[] called = new boolean[1]; 163 Handler handler = new Handler(Looper.getMainLooper()) { 164 @Override 165 public void handleMessage(Message msg) { 166 called[0] = true; 167 } 168 }; 169 handler.sendEmptyMessage(0); 170 Thread.sleep(SLEEP_TIME); 171 Assert.assertTrue(called[0]); 172 } 173 174 /** 175 * Ensures that the thread the test runs on has not been 176 * prepared as a looper. It doesn't make sense for it 177 * to be a looper because it will be blocked for the entire 178 * duration of test execution. Tests should instead post 179 * messages to the main looper or a new handler thread 180 * of their own as appropriate while running. 181 */ 182 @Test 183 public void testTestThreadIsNotALooper() { 184 Assert.assertNull(Looper.myLooper()); 185 } 186 187 /** 188 * Ensures that tests run on the same thread they were 189 * instantiated on. This is needed to ensure that 190 * objects created by the test don't accidentally bind 191 * to thread-local state belonging to other threads. 192 * In particular, this ensures that the test cannot 193 * create Handlers that are bound to the wrong thread. 194 */ 195 @Test 196 public void testTestRunsOnSameThreadAsInstantiation() { 197 Assert.assertEquals(Thread.currentThread(), mInstantiationThread); 198 } 199} 200