Django 4.x Test 单元测试使用示例和配置方法

测试是软件开发过程中必不可少的步骤。许多软件开发人员忽略了这一步并手动测试代码。

随着应用程序大小的增长,手动测试代码变得乏味。单元测试确保添加到应用程序的每个组件都按预期工作,而不会破坏其他功能的功能。

通过一个简单的应用程序结合API进行各个组件的编写和单元测试。


项目配置

默认已经安装了 Django 4.x 版本和 Rest Framework 模块。

创建项目。

django-admin startproject djangotesting

创建应用。

python manage.py startapp testing

settings.py 应用配置。

INSTALLED_APPS = [
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'testing',
 'rest_framework'
]

后端应用配置

models.py 创建表单

class Student(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    reg_number = models.CharField(max_length=50)
    date_of_admission = models.DateField(null=True, blank=True)

    def get_absolute_url(self):
        return reverse("student-detail", args=[str(self.id)])

    def __str__(self):
        return f"Name: {self.first_name} {self.last_name}"

serializers.py 数据序列化

class StudentSerializer(ModelSerializer):
     class Meta:
         model = Student
         fields = "__all__"

views.py 模型视图

# 普通视图
class StudentListView(generic.ListView):
     model = Student
     paginate_by = 10 


class StudentView(generic.DetailView):
     model = Student     


# API 视图
class CreateStudentApiView(generics.CreateAPIView):
     queryset = Student.objects.all()
     serializer_class = StudentSerializer

urls.py 路由设置

应用路由。

urlpatterns = [
    path('students', StudentListView.as_view(), name="students"),
    path('students/create', CreateStudentApiView.as_view(), name="create-student"),
    path('students/', StudentView.as_view(), name="student-detail")
]

项目路由。

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('testing.urls'))
]

templates 前端模板


        
                {% for student in student_list %}
                
                {% endfor %}
            
# First Last Reg. No.
{{ student.id }} {{ student.first_name }} {{ student.last_name }} {{ student.reg_number }}

开启服务

python manage.py makemigrations
python manage.py migrate
python manage.py runserver 0.0.0.0:8000


进行单元测试

应用项目下创建 tests_views.py 。

test_views 测试

  • @classmethod,用于创建存储在临时测试数据库中并在整个测试课程中使用的学生对象。
  • test_url_exists 方法向提供的路径发出 HTTP 请求并检查结果代码是否成功。
  • test_url_accessible_by_name 方法从给定的名称构造一个 URL 并向创建的 URL 发出 HTTP 请求,然后检查请求的状态代码。
  • test_view_uses_correct_template 方法检查访问指定路径时是否加载了正确的模板。
  • test_pagination_is_correct 方法测试返回的数据是否分页。
class StudentListViewTest(TestCase):
    @classmethod
    def setUpTestData(cls):
        number_of_students = 30
        for student_id in range(number_of_students):
            Student.objects.create(first_name=f"John{student_id}", last_name=f"Doe{student_id}")

    def test_url_exists(self):
        response = self.client.get("/students")
        self.assertEqual(response.status_code, 200)

    def test_url_accessible_by_name(self):
        response = self.client.get(reverse('students'))
        self.assertEqual(response.status_code, 200)

    def test_view_uses_correct_template(self):
        response = self.client.get(reverse('students'))
        self.assertEqual(response.status_code, 200)
        self.assertTemplateUsed(response, 'testing/student_list.html')

    def test_pagination_is_correct(self):
        response = self.client.get(reverse('students'))
        self.assertEqual(response.status_code, 200)
        self.assertTrue('is_paginated' in response.context)
        self.assertTrue(response.context['is_paginated'] is True)
        self.assertEqual(len(response.context['student_list']), 10)

test_models 测试

  • @classmethod,用于创建存储在临时测试数据库中并在整个测试课程中使用的学生对象。
  • setUpTestData 方法设置将在整个测试类中使用的对象。
  • test_string_methodstr 方法测试模型的方法返回的字符串是否Student有效。
  • test_get_absolute_url 方法测试从模型返回的绝对 URL 是否有效。
class StudentModelTestcase(TestCase):
    @classmethod
    def setUpTestData(cls):
        Student.objects.create(first_name="Peter", last_name="John", reg_number="111b2")

    def test_string_method(self):
        student = Student.objects.get(id=1)
        expected_string = f"Name: {student.first_name} {student.last_name}"
        self.assertEqual(str(student), expected_string)

    def test_get_absolute_url(self):
        student = Student.objects.get(id=1)
        self.assertEqual(student.get_absolute_url(), "/students/1")

tests_api_view 测试

student_creation_test 测试学生创建端点。在该方法中创建一个有效负载,其中包含创建学生所需的所有数据,然后 students/create 使用有效负载向端点发出 POST 请求。

class StudentSerializerTestCase(APITestCase):
    def student_creation_test(self):
        payload = {
            "first_name": "Joan",
            "last_name": "Keith",
            "reg_number": "Abrt1",
            "date_of_admission": datetime.date.today()
        }
        response = self.client.post(reverse("student-create"), payload)
        self.assertEqual(status.HTTP_201_CREATED, response.status_code)

执行单元测试

python manage.py test

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
../PycharmProjects/djangoTest/venv/lib/python3.8/site-packages/django/views/generic/list.py:86: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list:  QuerySet.
  return self.paginator_class(
----------------------------------------------------------------------
Ran 6 tests in 0.044s

OK
Destroying test database for alias 'default'...

Test 参数说明

DataBass TEST

详见数据仓库配置的内容,如果基于 @classmethod 的话可以无视。

TEST_RUNNER

用于启动测试套件的类的名称,默认即可。

TEST_RUNNER ='django.test.runner.DiscoverRunner'

TEST_NON_SERIALIZED_APPS

用于回滚模拟,在 TransactionTestCases 和数据库后端的测试之间恢复数据库状态而不进行事务处理应用列表。

TEST_NON_SERIALIZED_APPS = []




发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章