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

TDD-隔离测试

4 分钟· ·
随笔 编程 TDD
作者
Allen
一个强大、轻量级的 Hugo 主题。
目录

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

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
js的this引发的思考
2 分钟
随笔 编程
泛型继承的理解
1 分钟
随笔 编程
关于技术栈的总结
3 分钟
随笔 人生
《我编程,我快乐:程序员职业规划之道读后感
3 分钟
随笔 人生
八月杂感
1 分钟
随笔 人生