美文网首页TDD(测试驱动开发)
【django】TDD测试驱动开发

【django】TDD测试驱动开发

作者: MarcoHorse | 来源:发表于2018-05-21 15:33 被阅读2次

    测试驱动开发是python web开发里面一个很重要的角色!使用测试来推动开发的进程,通过测试用例的编写,对需求功能分解,使用过程和接口都进行了设计,而tdd里面的测试代码用例是对自己的代码最好的解释。测试驱动开发最重要的功能还在于保障代码的正确性,能够迅速发现、定位bug。而迅速发现、定位bug

    下面简单讲下python里面用到的三种单元测试框架

    1. unitest
    2. django.test
    3. rest-framework.test
    4. 如何编写单元测试

    1. unitest.TestCase 系统提供的测试工具

    unittest模块提供了一组丰富的工具来构建和运行测试。下面演示了这些工具的一小部分足以满足大多数用户的需求。
    下面是一个测试三种字符串方法的简短脚本:

    import unittest
    
    class TestStringMethods(unittest.TestCase):
    
        def test_upper(self):
            self.assertEqual('foo'.upper(), 'FOO')
    
        def test_isupper(self):
            self.assertTrue('FOO'.isupper())
            self.assertFalse('Foo'.isupper())
    
        def test_split(self):
            s = 'hello world'
            self.assertEqual(s.split(), ['hello', 'world'])
            # check that s.split fails when the separator is not a string
            with self.assertRaises(TypeError):
                s.split(2)
    
    if __name__ == '__main__':
        unittest.main()
    

    testcase是由子类化unittest.testcase创建的。这三个单独的测试是用名字以字母测试开始的方法定义的。这种命名约定通知测试运行者关于哪些方法表示测试。每个测试的关键是对断言()的调用,以检查预期的结果;断言()或断言错误()来验证一个条件;或者断言()来验证一个特定的异常是否被提高。这些方法被用来代替assert语句,这样测试运行者就可以累积所有的测试结果并生成报告。

    也可以使用以下两句话来代替上面代码的最后两行

    suite = unittest.TestLoader().loadTestsFromTestCase(TestStringMethods)
    unittest.TextTestRunner(verbosity=2).run(suite)
    

    2. django.testTestCase django框架提供的测试框架

    2.1 如何编写django的测试框架
    django.test依赖于python的unitest框架,testcase的测试方法依赖于类的方法定义测试

    from django.test import TestCase
    from myapp.models import Animal
    
    class AnimalTestCase(TestCase):
        def setUp(self):
            Animal.objects.create(name="lion", sound="roar")
            Animal.objects.create(name="cat", sound="meow")
    
        def test_animals_can_speak(self):
            """Animals that can speak are correctly identified"""
            lion = Animal.objects.get(name="lion")
            cat = Animal.objects.get(name="cat")
            self.assertEqual(lion.speak(), 'The lion says "roar"')
            self.assertEqual(cat.speak(), 'The cat says "meow"')
    

    2.2 如何运行django的测试框架
    当您运行测试时,测试实用程序的默认行为是在任何以test开头的文件中找到所有的测试用例(即unittest.testcase的子类),自动地从这些测试用例中构建一个测试套件,并运行该套件。您可以通过向。/manage提供任意数量的“测试标签”来指定要运行的特定测试。py测试。每个测试标签都可以是一个完整的Python点路径到一个包、模块、TestCase子类或测试方法。

    # Run all the tests in the animals.tests module
    $ ./manage.py test animals.tests
    
    # Run all the tests found within the 'animals' package
    $ ./manage.py test animals
    
    # Run just one test case
    $ ./manage.py test animals.tests.AnimalTestCase
    
    # Run just one test method
    $ ./manage.py test animals.tests.AnimalTestCase.test_animals_can_speak
    

    如果您在测试运行时按Ctrl-C,那么测试运行程序将等待当前运行的测试完成,然后优雅地退出。在一个优雅的退出过程中,测试运行程序将输出任何测试失败的详细信息,报告运行了多少测试以及遇到了多少错误和故障,并像往常一样销毁任何测试数据库。因此,如果您忘记传递-failfast选项,那么按Ctrl-C是非常有用的,注意一些测试出乎意料地失败,并且希望在不等待完整测试运行完成的情况下获得失败的详细信息。

    3. rest-framework.test基于restframework的api测试

    rft的创建测试请求和django的一致,所以其也可以实现self.get|post等系列请求

    class ProductViewTest(TestCassMixin, APITestCase):
        base_url = '/store/product'
        model = Product
        serializer_class = ProductSerializer
    
        def test_list_filter(self):
            """列表筛选功能"""
            url = f"{self.base_url}/"
            query_keys = ("brand", "type")
            foreign_keys = ("brand", )
    
            for key in query_keys:
                if key in foreign_keys:
                    val = getattr(self.product, key + "_id")
                else:
                    val = getattr(self.product, key)
    
                # 查询条件匹配,返回数据 > 0
                response = self.client.get(url, data={key: val})
                self.assertEqual(response.status_code, 200)  # 接口响应正确
                self.assertGreater(response.data['count'], 0)
    
                # 查询条件不匹配,返回数据 = 0
                response = self.client.get(url, data={key: val + 1})
                self.assertEqual(response.status_code, 200)  # 接口响应正确
                self.assertEqual(response.data['count'], 0)
    

    更多测试方式:http://www.django-rest-framework.org/api-guide/testing/

    4. 如何编写单元测试

    4.1 这个例子是测试myapp.models 中的 Animal 类相关的方法功能。

    from django.test import TestCase
    from myapp.models import Animal
     
     
    class AnimalTestCase(TestCase):
        def setUp(self):
            Animal.objects.create(name="lion", sound="roar")
            Animal.objects.create(name="cat", sound="meow")
     
        def test_animals_can_speak(self):
            """Animals that can speak are correctly identified"""
            lion = Animal.objects.get(name="lion")
            cat = Animal.objects.get(name="cat")
            self.assertEqual(lion.speak(), 'The lion says "roar"')
            self.assertEqual(cat.speak(), 'The cat says "meow"')
    

    4.2 用代码访问网址的方法:

    >>> from django.test import Client
    >>> c = Client()
    >>> response = c.post('/login/', {'username': 'john', 'password': 'smith'})
    >>> response.status_code
    200
    >>> response = c.get('/customer/details/')
    >>> response.content
    '<!DOCTYPE html...'
    

    我们可以用 django.test.Client 的实例来实现 get 或 post 内容,检查一个网址返回的网页源代码。

    默认情况下CSRF检查是被禁用的,如果测试需要,可以用下面的方法:

    >>> from django.test import Client
    >>> csrf_client = Client(enforce_csrf_checks=True)
    

    使用 csrf_client 这个实例进行请求即可。

    指定浏览USER-AGENT:

    >>> c = Client(HTTP_USER_AGENT='Mozilla/5.0')
    

    模拟post上传附件:

    from django.test import Client
    c = Client()
     
    with open('wishlist.doc') as fp:
        c.post('/customers/wishes/', {'name': 'fred', 'attachment': fp})
    

    测试网页返回状态:

    from django.test import TestCase
     
    class SimpleTest(TestCase):
        def test_details(self):
            response = self.client.get('/customer/details/')
            self.assertEqual(response.status_code, 200)
     
        def test_index(self):
            response = self.client.get('/customer/index/')
            self.assertEqual(response.status_code, 200)
    

    我们用 self.client 即可,不用 client = Client() 这样实例化,更方便,我们还可以继承 Client,添加一些其它方法:

    from django.test import TestCase, Client
     
    class MyTestClient(Client):
        # Specialized methods for your environment
        ...
         
    class MyTest(TestCase):
        client_class = MyTestClient
     
        def test_my_stuff(self):
            # Here self.client is an instance of MyTestClient...
            call_some_test_code()
    

    定制 self.client 的方法:

    from django.test import Client, TestCase
     
     
    class MyAppTests(TestCase):
        def setUp(self):
            super(MyAppTests, self).setUp()
            self.client = Client(enforce_csrf_checks=True)
     
        def test_home(self):
            response = self.client.get('/')
            self.assertEqual(response.status_code, 200)
    

    相关文章

      网友评论

        本文标题:【django】TDD测试驱动开发

        本文链接:https://www.haomeiwen.com/subject/vsifjftx.html