1.正常的开发流程
编码--->测试--->重复--->提交
基于测试驱动的开发
测试--->编码--->重复--->提交
先写了测试之后,由于测试的覆盖率要求为100%,所以就会让代码中可能存在的分支都进行测试,这样先写测试单元,可以为将来的代码提供一种有效的参考
举例说明:
package com.hust.junit.model;
/**
* Created by Administration on 2016/6/5.
*/
public class User {
private String username;
private String password;
private String nickname;
public User() {
}
public User(String username, String password, String nickname) {
this.username = username;
this.password = password;
this.nickname = nickname;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
@Override
public String toString() {
return "User{" +
"username='" + username + '\'' +
", password='" + password + '\'' +
", nickname='" + nickname + '\'' +
'}';
}
}
package com.hust.junit.service;
import com.hust.junit.model.User;
/**
* Created by Administration on 2016/6/5.
*/
public interface IUserService {
void add(User user);
void delete(String username);
User load(String username);
User login(String username, String password);
}
package com.hust.junit.service;
import com.hust.junit.model.User;
import com.hust.junit.model.UserException;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Administration on 2016/6/5.
*/
public class UserServiceByMap implements IUserService {
private Map<String, User> us = new HashMap<String, User>();
public void add(User user) {
if (load(user.getUsername()) != null) throw new UserException("用户名已经存在");
us.put(user.getUsername(), user);
}
public void delete(String username) {
us.remove(username);
}
public User load(String username) {
return us.get(username);
}
public User login(String username, String password) {
User u = load(username);
if (u == null) throw new UserException("用户名不存在");
if (!u.getPassword().equals(password)) throw new UserException("用户密码不存在");
return u;
}
}
package com.hust.junit.model;
/**
* Created by Administration on 2016/6/5.
*/
public class UserException extends RuntimeException {
public UserException() {
}
public UserException(String message) {
super(message);
}
public UserException(String message, Throwable cause) {
super(message, cause);
}
public UserException(Throwable cause) {
super(cause);
}
public UserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(cause);
}
}
package com.hust.junit.service;
import com.hust.junit.model.User;
import com.hust.junit.model.UserException;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by Administration on 2016/6/5.
*/
public class IUserServiceTest {
private IUserService us;
private User baseUser;
@Before
public void setUp() throws Exception {
us = new UserServiceByMap();
// us = new UserService();
baseUser = new User("admin", "admin", "管理员");
}
@After
public void tearDown() throws Exception {
}
private void assertUserEquals(User tu, User u) {
assertEquals("用户名不相同", tu.getUsername(), u.getUsername());
assertEquals("密码不相同", tu.getPassword(), u.getPassword());
assertEquals("昵称不相同", tu.getNickname(), u.getNickname());
}
@Test
public void add() {
User u = baseUser;
us.add(u);
User tu = us.load("admin");
assertNotNull("添加用户不成功", tu);
assertUserEquals(tu, u);
}
@Test(expected = UserException.class)
public void testAddExistUsername() throws Exception {
us.add(baseUser);
User tu = new User("admin", "admin", "管理员");
us.add(tu);
}
@Test
public void delete() throws Exception {
us.add(baseUser);
User tu = us.load(baseUser.getUsername());
assertNotNull("添加用户不成功", tu);
us.delete(baseUser.getUsername());
tu = us.load(baseUser.getUsername());
assertNull("删除的用户还存在", tu);
}
@Test
public void login() throws Exception {
us.add(baseUser);
String username = "admin";
String password = "admin";
User tu = us.login(username, password);
assertUserEquals(tu, baseUser);
}
@Test(expected = UserException.class)
public void testNotExistUserLogin() {
us.add(baseUser);
String username = "admin1";
String password = "admin";
us.login(username, password);
}
@Test(expected = UserException.class)
public void testPasswordErrorUserLogin() {
us.add(baseUser);
String username = "admin";
String password = "1234";
us.login(username, password);
}
}
2.cobertura的使用(推荐使用maven插件)
方式一.Maven依赖
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
<version>2.5.1</version>
</plugin>
执行cobertura:cobertura的命令
生成报告路径:
生成报告截图:
方式二:命令行方式
1、将cobertura的路径设置到path中
2、将要测试的源代码,编译之后的字节码文件和所需要的jar包拷贝到一个单独的目录中做处理
3、在命令提示符中使用命令为要生成测试覆盖率报告的代码生成一个ser的文件
3.1、生成cobertura.ser文件
cobertura-instrument--destination instrumented org/konghao/manager/(包的名称)
4、基于ser文件运行测试
4.1、java-cplib/junit-4.10.jar;lib/cobertura.jar;instrumented;.;-Dnet.sourceforge.cobertura.datafile=cobertura.serorg.junit.runner.JUnitCore org.konghao.manager.TestUserManager
5、根据ser文件生成测试覆盖率的报告
特别注意:如果文件的编码是utf-8的,在生成报告前需要为cobertura-report.bat文件增加DfileEncoding的处理
cobertura-report--format html --datafile cobertura.ser --destination reports src