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;
        }
    }
}

测试全部通过
在这里插入图片描述

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值