TDD测试驱动开发
Posted 赵jc
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TDD测试驱动开发相关的知识,希望对你有一定的参考价值。
TDD测试驱动开发
本文是参照依着风睡_hcg博主的文章写的,[链接地址],如有错误的地方,欢迎大家讨论 链接地址
什么是测试驱动开发
测试驱动开发(Test-Driven Development),是敏捷开发中的一项核心实践和技术。
TDD是在开发功能代码之前,先编写单元测试用例代码,测试代码确定需要编写什么代码产品,之后再开始真正的业务需求开发。
测试驱动开发该怎么做?
我们只要记住三部曲就可以了,变红–>变绿–>重构,现在你可能还不理解这是什么意思,看完以下的文章就懂啦!
基于Junit的简单实操
在进行 TDD 案例编写的时候,看一个简单的需求(经典案例):
- 输入一个非元音字符,并预期返回字符本身 (输入"h" 返回“h”)
- 输入一个元音(a,e,i,o,u),返回 mommy (输入"a" 返回“mommy”)
- 输入一个元音超过字符串的30%,元音字母被 mommy 替换(输入"ab" 返回“mommyb”)
- 输入一个元音超过30%,并且存在连续元音的字符串,并预期只被替换一次(输入"aab" 返回“mommyab”)
如果直接进行代码编写,靠大脑分析分析整理代码的逻辑,和书写步骤的时候比较繁琐。
那么接下来就看下这个案例在 TDD 中如何逐步成型的吧。
需求一:输入一个非元音字符,并预期返回字符本身 (输入"h" 返回“h”)
- 第一步:首先编写测试用例代码,运行。结果变红
。(测试用例未通过)
@Test
public void test()
String inputStr = "h";
String result = tddTest(inputStr);
Assert.assertEquals("h", result);
public String tddTest(String inputStr)
return null;
- 第二步:编写业务逻辑代码,运行。变绿
(测试用例通过)
public String tddTest(String inputStr)
return inputStr;
- 第三步:检查是否需要重构,这个需求不需要重构
需求二:输入一个元音(a,e,i,o,u),返回 mommy (输入"a" 返回“mommy”)
第一步:加入新的业务逻辑(输入元音字母返回特定的字符串)运行。结果变红
(测试用例未通过)
@Test
public void test1()
String inputStr = "h";
String result = tddTest(inputStr);
Assert.assertEquals("h", result);
@Test
public void test2()
String inputStr = "a";
String result = tddTest(inputStr);
Assert.assertEquals("mommy", result);
public String tddTest(String inputStr)
return inputStr;
- 第二步:编写业务逻辑代码,运行。变绿
(测试用例通过)
public String tddTest(String inputStr)
List<String> list = Arrays.asList("a","e","i","o","u");
if(list.contains(inputStr))
return "mommy";
else
return inputStr;
- 第三步:检查是否需要重构,这个需求不需要重构
需求三:加入新的业务逻辑(元音字符超过字符串的 30% ,被特定字符串替换)运行结果变红
- 第一步:加入新的业务逻辑(元音字符超过字符串的 30% ,被特定字符串替换)运行。结果变红
(测试用例未通过)
@Test
public void test1()
String inputStr = "h";
String result = tddTest(inputStr);
Assert.assertEquals("h", result);
@Test
public void test2()
String inputStr = "a";
String result = tddTest(inputStr);
Assert.assertEquals("mommy", result);
@Test
public void test3()
String inputStr = "ab";
String result = tddTest(inputStr);
Assert.assertEquals("mommyb", result);
- 第二步:编写业务逻辑代码,运行。变绿
(测试用例通过)
public String tddTest(String inputStr)
List<String> list = Arrays.asList("a", "e", "i", "o", "u");
StringBuffer ret = new StringBuffer();
int count = 0;
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
count++;
else
continue;
if((float)count / (float)inputStr.length() > 0.3)
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
ret.append("mommy");
else
ret.append(ch + "");
else
return inputStr;
return ret.toString();
- 第三步:检查是否需要重构,这个需求导致tddTest()函数的代码变得有点荣誉,所以需要进行代码的重构
计算元音在字符传中的数量,是一个独立的逻辑,可以进行方法抽取
private static int getYuanyinCount(List list, String inputStr)
int count = 0;
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
count++;
else
continue;
return count;
也可以对元音替换方法进行抽取
private static String replace(List list, String inputStr)
StringBuffer ret = new StringBuffer();
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
ret.append(REPLACE_CONSTANT);
else
ret.append(ch + "");
return ret.toString();
最后 : 对数字和字符串进行定义常量
private final static double VOWEL_PERCENT = 0.3;
private final static String REPLACE_CONSTANT = "mommy";
重构后的代码是以下代码:是不是看起来简洁了许多,而且也易于维护和拓展
private final static double VOWEL_PERCENT = 0.3;
private final static String REPLACE_CONSTANT = "mommy";
private static int getYuanyinCount(List list, String inputStr)
int count = 0;
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
count++;
else
continue;
return count;
private static String replace(List list, String inputStr)
StringBuffer ret = new StringBuffer();
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
ret.append(REPLACE_CONSTANT);
else
ret.append(ch + "");
return ret.toString();
public String tddTest(String inputStr)
List<String> list = Arrays.asList("a", "e", "i", "o", "u");
int count = getYuanyinCount(list, inputStr);
if((float)count / (float)inputStr.length() > VOWEL_PERCENT)
return replace(list, inputStr);
else
return inputStr;
需求四:加入新的业务逻辑(连续元音的字符串,并预期只被替换一次)运行结果变红
- 第一步:加入新的业务逻辑连续元音的字符串,并预期只被替换一次)运行。结果变红
(测试用例未通过)
@Test
public void test4()
String inputStr = "aaabb";
String result = tddTest(inputStr);
Assert.assertEquals("mommyaabb", result);
第二步:修改业务逻辑,由于对元音替换我们前面已经进行了方法抽取,所以没必要在主方法中进行修改开发。变绿
(测试用例通过)
private static String replace(List list, String inputStr)
StringBuffer ret = new StringBuffer();
int i = 0;
while(i < inputStr.length())
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
ret.append(REPLACE_CONSTANT);
while(i < inputStr.length() - 1 && inputStr.charAt(i + 1) == ch)
ret.append(ch + "");
i++;
else
ret.append(ch + "");
i++;
return ret.toString();
自此,开发基本完成,我又对多种情况的可能性,进尽可能的减少,行了进一步的修改和完善,使得 bug 数量以及后续的维护尽可能的减少。其中可能存在大量的不完美的代码和不健全的业务逻辑,如果读者有发现可以和我提出来,尽可能的改善。
完整代码
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
public class testDemo
private final static double VOWEL_PERCENT = 0.3;
private final static String REPLACE_CONSTANT = "mommy";
@Test
public void test1()
String inputStr = "h";
String result = tddTest(inputStr);
Assert.assertEquals("h", result);
@Test
public void test2()
String inputStr = "a";
String result = tddTest(inputStr);
Assert.assertEquals("mommy", result);
@Test
public void test3()
String inputStr = "ab";
String result = tddTest(inputStr);
Assert.assertEquals("mommyb", result);
@Test
public void test4()
String inputStr = "aaabb";
String result = tddTest(inputStr);
Assert.assertEquals("mommyaabb", result);
private static int getYuanyinCount(List list, String inputStr)
int count = 0;
for(int i = 0; i < inputStr.length(); i++)
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
count++;
else
continue;
return count;
private static String replace(List list, String inputStr)
StringBuffer ret = new StringBuffer();
int i = 0;
while(i < inputStr.length())
char ch = inputStr.charAt(i);
if(list.contains(ch + ""))
ret.append(REPLACE_CONSTANT);
while(i < inputStr.length() - 1 && inputStr.charAt(i + 1) == ch)
ret.append(ch + "");
i++;
else
ret.append(ch + "");
i++;
return ret.toString();
public String tddTest(String inputStr)
List<String> list = Arrays.asList("a", "e", "i", "o", "u");
int count = getYuanyinCount(list, inputStr);
if((float)count / (float)inputStr.length() > VOWEL_PERCENT)
return replace(list, inputStr);
else
return inputStr;
测试全部通过
以上是关于TDD测试驱动开发的主要内容,如果未能解决你的问题,请参考以下文章