作为测试先行的开发方法规定,首先要写单元测试。测试预期和定义了要被测试的功能设计。我们需要获得一个用户名和密码,然后返回一个登录成功或者登录失败。一个用来判断的接口方法来做刚才所述的
boolean login(String username, String password);
测试类LoginDialogTest 将测试这个功能。例1展示了在LoginDialogTest.java. 文件中他的初始实现。
LoginDialogTest.java
import junit.framework.*;
public class LoginDialogTest extends TestCase {
public void testLogin() {
LoginDialog dialog = new LoginDialog();
assertTrue( dialog.login("user", "passwd") ); }
}
这个测试是基于JUnit基础测试类TestCase的。测试方法testLogin()创建了一个LoginDialog 的实例,调用了他的login()方法,然后判定结果是真。这段代码将不会编译,因为LoginDialog 不存在。在TDD过程后,LoginDialog
将生成和保存,代码编译后,测试运行验证将象预期的那样失败(因为方法没有实现)。然后 LoginDialog 为了通过单元测试给出最小的实现,遵照敏捷的圣条 做 可能工作的最简单的事情(the simplest thing that could possibly work)。例2展示了最初的LoginDialog 版本,用最少的代码通过了单元测试,实现在LoginDialog.java. 文件里。
LoginDialog.java
public class LoginDialog {
LoginDialog() {}
public boolean login(String username, String password)
{ return true; }
}
使用下面的命令来运行代码
javac -classpath ".;junit.jar" LoginDialogTest.java
javac -classpath "." LoginDialog.java
classpath 必须包括junit.jar 来运行单元测试,因为他使用了JUnit.在Linux,Mac OSX,还有其他的UNIX系统上,classpath将包含一个冒号(:)而不是想下面那样用一个分号。
测试将如下运行
java -classpath ".;junit.jar" junit.textui.TestRunner LoginDialogTest
单元测试通过了,真好!不幸的是,这个编码只是模拟一下。Login()方法将总是批准登录。毋庸置疑,客户将不会欣赏这种水平的安全机制。显然,要写的下一个测试是验证如果给的条件不正确的话将失败。例3展示了LoginDialogTest 的第二个测试方法去实现这个目的,testLoginFail() 。既然两个测试都使用一个LoginDialog 的实例,测试类被重构为在他的setUp() 方法里创建一个固定的测试用的
LoginDialog。
LoginDialogTest.java
import junit.framework.*;
public class LoginDialogTest extends TestCase {
private LoginDialog dialog; public void setUp() {
dialog = new LoginDialog();
}
public void testLogin() {
assertTrue( dialog.login("user", "passwd") );
}
public void testLoginFail() {
assertFalse( dialog.login("", "") );
}
}
LoginDialog 必须得通过新的测试,不能在第一次测试的时候有失败。TDD过程引导我们构造我们需要的真正的功能,在用正确的用户名和密码登录的时候,能成功登录,如果不是,就失败。例4展示了按此修改的LoginDialog
LoginDialog.java
public class LoginDialog {
private String user = "user";
private String passwd = "passwd";
LoginDialog() {} public boolean login(String username, String password) {
if (user.equals(username) && passwd.equals(password))
return true;
else return false; }
}
LoginDialog 现在能通过所有的测试。为此,他包括了符合成功登录条件的用户名和密码域。显然,这只是比第一个版本的安全性能稍微好一些。登录代码不应该包含认证的硬编码!基于这点,我们应该引入一个单独的类来包含LoginDialog 用的验证用户的登录信息。然而,这个例子是关于GUI构造的,那让我们暂停这个不安全的登录代码,继续GUI方面。