Lec 7 - Testing
TestSort()
- Write testSort first
- JUnit测试框架
首先import类。
import org.junit.Test;
import static org.junit.Assert.*;
写测试方法
public static void testSort() {
String[] input = {"i", "have", "an", "egg"};
String[] expected = {"an", "egg", "have", "i"};
Sort.sort(input);
assertArrayEquals(expected, input);
}
先建一个空sort(),观察assertArrayEquals形式。
Sort.sort()
其实是一个很简单的冒泡排序法,不过这里老师讲了一些coding和testing的思想,很受用。
My version
public static void sort(int[] nums) {
int min_num = 0, index = 0, temp = 0;
for (int i = 0; i < nums.length - 1; i += 1) {
min_num = nums[i];
index = i;
for (int j = i + 1; j < nums.length; j += 1) {
if (min_num > nums[j]) {
min_num = nums[j];
index = j;
}
}
temp = nums[i];
nums[i] = nums[index];
nums[index] = temp;
}
}
就是一口气编到底。PS. 这里我直接排的数字,因为先自己写了一遍不知道String怎么比大小等着他一会讲。。
Josh Hug
- Find the smallest item
- Move it to the front
- Selection sort the remaining N-1 items
一步一步来。首先实现1,找到最小的item。
/* Return the index of the smallest string from a particular start */
private static int findSmallest(String[] x, int start) {
int smallestIndex = start;
for (int i = start; i < x.length; i += 1) {
// A string compare method.
int cmp = x[i].compareTo(x[smallestIndex]);
if (cmp < 0) {
smallestIndex = i;
}
}
return smallestIndex;
}
string1.compareTo(string2) 实现比较两字符串大小,如string1小于string2返回-1
遍历start到最后一个元素
注意:这里的start形参其实是后来才知道要加的,因为后面会用recursion的方式实现sort
然后实现2,交换当前位置与最小string所在位置
private static void swap(String[] x, int a, int b) {
String temp = x[a];
x[a] = x[b];
x[b] = temp;
}
第三步,关键一步,运用recursion
public static void sort(String[] x) {
int smallestIndex = findSmallest(x);
swap(x, 0, smallestIndex);
sort(x[1:]);
}
如上,java中不存在数组切片操作,所以最后一步的剩下N-1个元素排序不好实现。所以,参照上一章中的resize方法,再另外构造一个sort方法,实现从start位置开始排序,然后,在sort中调用。
public static void sort(String[] x) {
sort(x, 0);
}
构造sort(string[] x, int start),实现从start位置开始排序
public static void sort(String[] x, int start) {
if (start == x.length - 1) {
return;
}
int smallestIndex = findSmallest(x, start);
swap(x, start, smallestIndex);
sort(x, start + 1);
}
所以,此时重新构造了findSmallest,加入新形参start,功能变为返回从start开始最小值的位置。
我之前一直以为只有有返回值的函数才能recursion,还是理解不深入。其实recursion理解成套娃就好了。
总结1
其实一开始接触project 0的时候就发现了,老师建方法特别详细,这一章里解释了原因。因为我们可以分别测试每一个方法,保证它是正确的然后再进行下一步,防止开发大型项目的时候从头开始找问题。并且方便优化。这种分布思想对我现在还是挺难的,在刷算法题的时候我总是想好总体思路,然后就开始走一步看一步,没有分块的能力。
PS. 方法应设置成private,只在类内调用。但为了测试,只能暂时变成public否则无法在测试类中调用。后面josh hug说会有更好的方法
Annotation
@Test
public void testSort() {
String[] input = {"i", "have", "an", "egg"};
String[] expected = {"a", "egg", "have", "i"};
Sort.sort(input);
assertArrayEquals(expected, input);
}
目前的理解是加入@Test(Test是库中的一个类),可实现在Test中运行主函数,可以删除TestSort中的main了,同时要求方法不能是static。此外还可以分别测试每个方法,分别输出。挺方便的功能。
总结2
- Autograder Driven Development
即写完整个程序 - 编译 - bug - 发给Autograder(josh写的批改器) - 接着改错 - 循环
又慢又累
- Unit Tests
写完一部分 - 对应的test方法进行测试 - 测试完毕 - 下一部分
or
先写Test方法,然后编写方法通过测试
测试感觉还是挺麻烦的。