public class Calculator {
public int add(int one, int another) {
return one + another;
}
public int multiply(int one, int another) {
return one * another;
}
如果不使用单元测试框架,我们可能需要这样来验证这段代码的正确性:
public class CalculatorTest {
public static void main(String[] args) {
Calculator calculator = new Calculator();
int sum = calculator.add(1, 2);
if(sum == 3) {
System.out.println("add() works!")
} else {
System.out.println("add() does not works!")
}
int product = calculator.multiply(2, 4);
if (product == 8) {
System.out.println("multiply() works!")
} else {
System.out.println("multiply() does not works!")
}
}
}
这个时候我们来写单元测试,你一开始就会发现你没有办法新建一个Context对象来读取String.xml,即使你想尽任何方法新建一个ContextImpl实例,最后你还是会出错的,主要原因再在于Gradle运行Local Unit Test 所使用的android.jar里面所有API都是空实现,并抛出异常的。 现在想想,我们实际上并不需要真的读取String.xml,我们需要验证的是记录在我们的关键列表集合是否生效,既然这样,我们前面说过了,Mockito的两个重要的功能是,验证Mock对象的方法的调用和可以指定mock对象的某些方法的行为。我们是否可以Mock一个Context对象并且指定它读取String.xml的行为?答案是可以的,如下就是使用Mockito的一段测试代码
public class TestListFilter2 {
@Mock
Context mContext;
@Mock
Resources mResources;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
Mockito.when(mContext.getResources()).thenReturn(mResources);
Mockito.when(mResources.getStringArray(R.array.default_core_list)).thenReturn(getEssentialProcessArray());
//模拟加载XML资源
EssentialProcessFilter.loadCoreList(mContext);
}
/**
* 测试关键服务的过滤器
*/
@Test
public void testEssentialFilter() {
EssentialProcessFilter processFilter = new EssentialProcessFilter();
ListFilter listFilter = Mockito.spy(ListFilter.class);
listFilter.addFilter(processFilter);
List list = new ArrayList();
list.addAll(getEssentialAppBean());
list.addAll(getNormalRunningApp());
List result = Mockito.mock(ArrayList.class);
for (RunningAppBean runningAppBean : list) {
if (listFilter.accept(runningAppBean)) {
result.add(runningAppBean);
}
}
Mockito.verify(listFilter, Mockito.times(list.size())).accept(Mockito.any(RunningAppBean.class));
Mockito.verify(result, Mockito.times(getNormalRunningApp().size())).add(Mockito.any(RunningAppBean.class));
}
/**
* 关键服务应用包名
*/
public String[] getEssentialProcessArray() {
return new String[]{"android.process.acore", "android.process.media", "android.tts", "android.uid.phone", "android.uid.shared", "android.uid.system"};
}
}
public class LoginPresenter {
private final LoginView mLoginView;
private final UserManager mUserManager;
//将UserManager作为构造方法参数传进来
public LoginPresenter(LoginView loginView,UserManager userManager) {
this.mLoginView = loginView;
this.mUserManager = userManager;
}
public void login(String username, String password) {
//... some other code
mUserManager.performLogin(username, password);
}
}
Instrumented Unit tests是需要运行再Android设备上的(物理/虚拟),通常我们使用Mock的方式不能很好解决对Android的API的依赖的这个问题,而使用这种测试方式可以依赖Android的API,使用Android提供的Instrumentation系统,将单元测试代码运行在模拟器或者是真机上,但很多情况来说,我们还是会需要和Mockito一起使用的。这中方案速度相对慢,因为每次运行一次单元测试,都需要将整个项目打包成apk,上传到模拟器或真机上,就跟运行了一次app似得,所以。
配置
测试代码目录:module-name/src/androidTests/java/
一般使用到的测试框架
AndroidJUnitRunner : JUnit 4-compatible test runner for Android
Espresso :UI testing framework; suitable for functional UI testing within an app
UI Automator :UI testing framework; suitable for cross-app functional UI testing across system and installed apps
public static ViewAssertion matches(final Matcher super View> viewMatcher) {}
下面是测试主页部分UI测试的代码
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityUITest {
/**
* {@link ActivityTestRule} is a JUnit {@link Rule @Rule} to launch your activity under test.
*
* Rules are interceptors which are executed for each test method and are important building
* blocks of Junit tests.
*/
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule(MainActivity.class, true, false);
//默认在测试之前启动该Activity
// public ActivityTestRule mActivityRule = new ActivityTestRule(MainActivity.class);
@Test
public void testNavigateToAdvanceFragment() {
Intent intent = new Intent();
//携带信息的方式启动Activity
intent.putExtra("EXTRA", "Test");
mActivityRule.launchActivity(intent);
// Open Drawer to click on navigation.
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
.check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT)))
.perform(DrawerActions.open()); // Open Drawer
// navigate to advance fragment.
Espresso.onView(ViewMatchers.withText(R.string.advanced_settings_group_title_advanced_features))
.perform(ViewActions.click());
// Left Drawer should be closed.
Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
.check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT)));
Espresso.onView(ViewMatchers.withText(R.string.fingerprint_settings_title)).check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
}
}
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityUITest {
/**
* {@link ActivityTestRule} is a JUnit {@link Rule @Rule} to launch your activity under test.
*
* Rules are interceptors which are executed for each test method and are important building
* blocks of Junit tests.
*/
@Rule
public ActivityTestRule mActivityRule = new ActivityTestRule(MainActivity.class, true, false);
@Test
public void testLockFirstItem() throws InterruptedException {
Intent intent = new Intent();
intent.putExtra("EXTRA", "Test");
mActivityRule.launchActivity(intent);
onData(allOf(is(instanceOf(LockerItem.class)),lockItemMatcher("WeChat"))).inAdapterView(withId(R.id.main_list)).onChildView(withId(R.id.item_ripple)).perform(click());
//...
}
/**
* 查找指定关键字的搜索条件
* @param name 需要搜索的关键字
*/
public static Matcher lockItemMatcher(final String name) {
return new BoundedMatcher(LockerItem.class) {
@Override
protected boolean matchesSafely(LockerItem item) {
return item != null && item.getTitle().equals(name);
}
@Override
public void describeTo(Description description) {
description.appendText("SearchItem has Name: " + name);
}
};
}
}
1. If语句作为表达式
val properties = if (jobIdToActiveJob.contains(jobId)) {
jobIdToActiveJob(stage.jobId).properties
} else {
// this stage will be assigned to "default" po
基础测试题
卷面上不能出现任何的涂写文字,所有的答案要求写在答题纸上,考卷不得带走。
选择题
1、 What will happen when you attempt to compile and run the following code? (3)
public class Static {
static {
int x = 5; // 在static内有效
}
st
表里的一行对于一个数据块太大的情况有二种(一行在一个数据块里放不下)
第一种情况:
INSERT的时候,INSERT时候行的大小就超一个块的大小。Oracle把这行的数据存储在一连串的数据块里(Oracle Stores the data for the row in a chain of data blocks),这种情况称为行链接(Row Chain),一般不可避免(除非使用更大的数据
Follow up for "Remove Duplicates":What if duplicates are allowed at most twice?
For example,Given sorted array nums = [1,1,1,2,2,3],
Your function should return length