经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Django » 查看文章
Python项目维护不了?可能是测试没到位。Django的单元测试和集成测试初探
来源:cnblogs  作者:程序设计实验室  时间:2024/3/7 9:09:03  对本文有异议

前言

好久没搞 Django 了,最近维护一个我之前用 Django 开发的项目竟然有亲切的感觉??

测试,在以前确实是经常被忽略的话题,特别是对于 Python Web 这种快速开发框架,怎么敏捷怎么来,快速开发快速上线,而不是慢工出细活做得很规范,往往也是因为这种粗狂的开发风格,导致项目后续难以维护,这时候再给 Python 冠上一个开发容易维护难的名字。

Python: 我不背这锅??

说回正题,这次的测试包括两部分,在 Django 项目内部写单元测试和集成测试,保证项目功能正常,然后我还开发了一个独立的自动测试工具,可以根据 OpenAPI 的文档来测试,并且在测试完成后输出测试报告,报告内容包括每个接口是否测试通过和响应时间等。

这个工具我使用了 go 语言开发,主要是考虑到了 go 语言可以傻瓜式的实现交叉编译,生成的可执行文件直接上传到服务器就可以执行,非常方便。

这个自动测试工具我会在下一篇文件介绍。

Django 的测试

不得不说 Django 的文档写得真不错??

我看了一会文档就开始写测试,Django 全家桶真的舒服,开发体验太丝滑了

使用 startapp 创建 app 的时候,每个 app 目录下都有个 tests.py 文件,我们的测试代码就写在这个文件里面好了。

如果测试代码很多的话,还可以拆分,如何拆分参考 views.py 的拆分,把 tests.py 改成 package ,即创建个 tests 目录,下面放各个测试文件,然后在 __init__.py 里引入。

测试分为单元测试和集成测试,在 Django 里写单元测试比 AspNetCore 舒服多了,不用考虑依赖注入的问题,Django 全给你处理好了。

在测试的时候,Django 会自动创建测试数据库,因此也不用自己去折腾环境隔离啥的。

关于这俩种测试的区别,我之前的文章里有介绍,就不复制粘贴了。

Asp-Net-Core学习笔记:单元测试和集成测试

例子

这次以两个 app 为例

  • config - 单元测试
  • dashboard - 集成测试

在 Django 里这俩种测试都没啥心智负担,也不用啥额外的操作,直接在 tests.py 里写就完事了。

单元测试

以 config app 作为单元测试的例子

我封装了一个 ConfigService 代码如下

  1. from datetime import date
  2. from .models import CommonConfig
  3. class ConfigService(object):
  4. def __init__(self):
  5. ...
  6. @staticmethod
  7. def get_config(key: str) -> str:
  8. queryset = CommonConfig.objects.filter(key=key)
  9. if queryset.exists():
  10. return queryset.first().value
  11. return ''
  12. @property
  13. def today(self):
  14. return date.today()
  15. @property
  16. def start_year(self):
  17. value = self.get_config('start_year')
  18. return str(self.today.year) if len(value) == 0 else value
  19. @property
  20. def start_month(self):
  21. value = self.get_config('start_month')
  22. return str(self.today.month) if len(value) == 0 else value
  23. @property
  24. def end_year(self):
  25. value = self.get_config('end_year')
  26. return str(self.today.year) if len(value) == 0 else value
  27. @property
  28. def end_month(self):
  29. value = self.get_config('end_month')
  30. return str(self.today.month) if len(value) == 0 else value

编辑 apps/config/tests.py

  1. from django.test import TestCase
  2. from apps.config.models import CommonConfig
  3. from apps.config.services import ConfigService
  4. class CommonConfigTestCase(TestCase):
  5. def setUp(self):
  6. CommonConfig.objects.create(key='start_year', value='2023')
  7. CommonConfig.objects.create(key='end_year', value='2024')
  8. CommonConfig.objects.create(key='start_month', value='1')
  9. CommonConfig.objects.create(key='end_month', value='10')
  10. def test_common_config(self):
  11. cfg = ConfigService()
  12. self.assertEqual(cfg.start_year, '2023')
  13. self.assertEqual(cfg.end_year, '2024')
  14. self.assertEqual(cfg.start_month, '1')
  15. self.assertEqual(cfg.end_month, '10')

集成测试

集成测试是模拟 HTTP 请求去访问接口,看看接口正不正常。

Django 的 TestCase 类里自带了 client 属性,可以很方便的请求接口。

一般接口都要登录才能用,然后 client 里也很贴心的集成了 Django 的认证授权体系,直接 login 就完事了。

注意测试的时候是自动创建了临时数据库,所以得先添加用户。

接着调用 self.client.get, self.client.post 之类的方法去测试接口就好了。

  1. from django.test import TestCase
  2. from django.shortcuts import reverse
  3. from django.contrib.auth.models import User
  4. from rest_framework import status
  5. class DashboardTests(TestCase):
  6. def setUp(self):
  7. User.objects.create_user(username='user', password='pwd')
  8. self.client.login(username="user", password="pwd")
  9. def test_overview(self):
  10. resp = self.client.get(reverse('dashboard:overview'), {'grant_year': 2023, 'grant_month': 2})
  11. self.assertEqual(resp.status_code, status.HTTP_200_OK)
  12. self.assertEqual(resp.json()['code'], status.HTTP_200_OK)
  13. def test_monthly_data(self):
  14. resp = self.client.get(reverse('dashboard:monthly_data'), {'grant_year': 2023, 'grant_month': 2})
  15. self.assertEqual(resp.status_code, status.HTTP_200_OK)
  16. self.assertEqual(resp.json()['code'], status.HTTP_200_OK)
  17. def test_county_data(self):
  18. resp = self.client.get(reverse('dashboard:county_data'), {'grant_year': 2023, 'grant_month': 2})
  19. self.assertEqual(resp.status_code, status.HTTP_200_OK)
  20. self.assertEqual(resp.json()['code'], status.HTTP_200_OK)

运行测试

测试写完之后

使用命令运行测试

  1. python manage.py test

还有其他参数请参考官方文档

不过运行测试的时候就没有 AspNetCore 爽了,没有那种一个个接口相继亮起绿灯的快感;

Django 的测试只能看到测试结果,有多少个测试通过了,如果有报错会看到 Traceback 信息。

  1. $ python .\manage.py test
  2. Found 5 test(s).
  3. Creating test database for alias 'default'...
  4. System check identified no issues (0 silenced).
  5. .....
  6. ----------------------------------------------------------------------
  7. Ran 5 tests in 0.831s
  8. OK
  9. Destroying test database for alias 'default'...

小结

Django 还是熟悉的味道,好用就对了。

参考资料

没想到不知不觉中 Django 刷版本号到 5.0 了…

原文链接:https://www.cnblogs.com/deali/p/18057931

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号