跳过正文
  1. 博客/
  2. 随笔/
  3. 编程/

TDD-隔离测试

·4 分钟· ·
随笔 编程 TDD
目录

隔离测试是相对与于整合测试来说的,现代软件架构流行分层式、模块化,而隔离测试就是相当于在每层上进行测试,整合测试就是跨越多个层进行测试

introduction
#

举个简单例子来说,在django系列中,我们把表单提交分成两个层,一个form层,一个式model

form层相当于接近用户交互层,而model层与数据库联系更大, form层负责获取用户数据并验证,而model层根据form层数据将数据存入数据库。

隔离测试就是隔离form层向model层提交,而整合测试就是直接测试form层和model层。

判断一个测试是整合测试还是隔离测试就是看测试的边界,整合测试相当于我们更加熟悉,我们测试时通过伪造form提交,然后通过数据库获取存入数据来得到验证,而隔离测试就比较复杂,因为我们很难在一个耦合度高代码找到怎么隔离两个层的方法。

接下来我就介绍python里一个神器:mock

自己用过其他语言框架中的mock,但是python里面mock里面最神奇的的是里面的patch,就像一个超级补丁一样。

Example
#

接下来我用一个例子来介绍一下如何写隔离测试

首先我们在 lists.forms.py中一个表单model

    class ListForm(forms.models.ModelForm):  
        def save(self):  
            pass  

我们在lists.models.py有个model

    class List(models.Model):  
        def create_now():  
            pass  

现在来分析一下这个隔离测试,我们要测试ListFormsave方法

首先ListFormList两个类是耦合的,一个整合测试,我们只要调用save方法,然后查询数据库就可以完成这个测试,然而隔离测试不同,我们只能测试在调用save方法时,他“干”了什么。他可能调用了Listcreate_now方法,将得到表单数据传了过去。

意味着我们只能测试到save方法调用了List方法。

那这个隔离单元测试该怎么写?

接下来我们隆重介绍mock里面的最强补丁patch

根据TDD原则,我们先新建一个单元测试IsolutionFormTest

    import unittest  
    from unittest.mock import patch, Mock      ##load super patch   
    from lists.models import List  
    from lists.forms import ListForm  
      
      
    class IsolutionFormTest(unitest.TestCase):  
             
           @patch('lists.forms.List.create_new')  
           def test_save_creates_new_list(self, mock_list_create_new):  
                form = ListForm(data={'text': "example text"})  
                form.is_valid()    # get clean data  
                form.save()  
                  
                mock_list_create_new.assert_called_once_with(  
                    text= "example text"  
                )   # the major test  

我来介绍一下这个patch,就像名字一样补丁,通过我们使用字符串将要替换的函数写出来,当test运行时,会自动将函数替换成一个mock对象,通过参数(上面的mock_list_create_new)赋给函数。

你可以这样想象,当form.save()调用时,在save函数里面,我们如果使用了lists.forms.List.create_new这个函数,这个函数就会被直接被补丁替换掉,你如果使用了lists.forms.List.create_new(text="xxx")就会变成mock_list_create_new(text="xxx"),当你调用了mock_list_create_new(text="xxx")时,mock_list_create_new这个mock对象就会记录下来。

这样我们就通过mock_list_create_new测试了函数是否执行了没有,因为隔离开form层和model层的就是通过两者之间的接口。我们只用测试接口是否执行了没有就可以了。

这样我们就完成了隔离单元测试,运行一下肯定失败,我们接下来就把save方法完善一下通过测试。

    from django import form  
    form list.models import List  
      
    class ListForm(forms.models.ModelForm):  
        def save(self):  
            List.create_new(text=self.cleaned_data['text'])  

ok测试通过了,我们就可以歇一口气了。

Conclusion
#

相对于整合测试,隔离测试运行速度更快,但是相对的隔离测试对接口要求非常严格,好的方面利用我们进行更好的代码设计,更好的分析代码的复杂程度,并且当接口变迁的时候,隔离测试能迅速发现变化而报警,然而隔离测试工作量比较大,而且没有整合测试那么好理解。在实际生产中对于复杂的接口我们尽量进行隔离测试,对于简单接口我们使用整合测试能根据减少程序的耦合性,而且能迅速发现集成问题。

ps:对patch感兴趣的童鞋可以自行google,patch好玩的地方还有很多,这里为了篇幅我只介绍了最核心的使用方法,大家可以自行探索patch更多好玩的东西。s

相关文章

TDD测试开发理解
·3 分钟
随笔 编程 TDD
看了 « Python Web 开发 测试驱动方法» 以后, 感觉自己找到自己的一些项目之所以不能够很好的 维护下去的原因.总结了一下自己的理解, 记录下来.
js的this引发的思考
·2 分钟
随笔 编程
最近这几天在开发一个hmtl5的游戏, 但是对于js怎么使用面对对象来编程有点困惑,查了一些资料 整理如下.
泛型继承的理解
·1 分钟
随笔 编程
泛型对于解决面对对象编程的算法设计可以提高其运算速度,但是对于引用类型来说还是没什么差别,因为引用类型只是指针的地址的调用,简单来说泛型还是挺好理解的,但是对于泛型、非泛型、继承和接口的融合就有些迷惑了。 # 比如说这种接口 # public interface IEnumeratot<T>:IDisposable,IEnumerator,ICompare<T> 这个泛型接口继承了两个非泛型接口,和一个泛型接口。 # 我一开始理解泛型就是一个个模型,只要我们把类型一个参数赋给他,他就能生成一个标准的类型,他缺少的只是一个参数而已,我们引用的时候感觉就像我们引用一个“全体方法”,把参数赋给类型后就可以一直调用类中的方法了,但是对于接口的继承如何理解? # 对于泛型类的继承,继承的类必须实现泛型的参数或者保留泛型的参数,比如下面
关于技术栈的总结
·3 分钟
随笔 人生
这段时间重新学习了web前端的技术栈,其实一开始加入社团时就是从前端开始入门的,等到了会仿写几个页面后就跳到了后端的坑,从html、css、js(只学了一点)又马不停蹄的转到.net平台、后来在老司机的带领下我们放弃了不开放的.net平台投入了python的怀抱
《我编程,我快乐:程序员职业规划之道读后感
·3 分钟
随笔 人生
一眨眼,四年过去了,再过几年就到了三十而立的年龄了,年轻的时候走马观花, 好像一直为了学习而学习,为了规划而规划,在经过被社会的毒打之后, 自己眼睛里面好像也没有当年的光了
八月杂感
·1 分钟
随笔 人生
一眨眼暑假就要过完了,这段博客又停下来了,倒不是因为我停下来学东西,而是我又忘了去归纳总结自己学的东西,总是一个鲁莽的心态去学,总感觉停下来会阻挡自己学习的脚步,但是其实写博客也是学习,把自己的学到的知识转换成自己的东西,写出来的过程就是帮自己的过程,其实这个方法也是一个非常牛逼的学习的方法叫做费尔曼学习法