以 CategoryViewTestCase 为例:
class CategoryViewTestCase(BlogDataTestCase): def setUp(self): super().setUp() self.url = reverse('blog:category', kwargs={'pk': self.cate1.pk}) self.url2 = reverse('blog:category', kwargs={'pk': self.cate2.pk}) def test_visit_a_nonexistent_category(self): url = reverse('blog:category', kwargs={'pk': 100}) response = self.client.get(url) self.assertEqual(response.status_code, 404) def test_without_any_post(self): Post.objects.all().delete() response = self.client.get(self.url2) self.assertEqual(response.status_code, 200) self.assertTemplateUsed('blog/index.html') self.assertContains(response, '暂时还没有发布的文章!') def test_with_posts(self): response = self.client.get(self.url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed('blog/index.html') self.assertContains(response, self.post1.title) self.assertIn('post_list', response.context) self.assertIn('is_paginated', response.context) self.assertIn('page_obj', response.context) self.assertEqual(response.context['post_list'].count(), 1) expected_qs = self.cate1.post_set.all().order_by('-created_time') self.assertQuerysetEqual(response.context['post_list'], [repr(p) for p in expected_qs])这个类首先继承自 BlogDataTestCase,setUp 方法别忘了调用父类的 stepUp 方法,以便在每个测试案例运行时,设置好博客测试数据。
然后就是进行了3个案例测试:
访问一个不存在的分类,预期返回 404 响应码。
没有文章的分类,返回200,但提示暂时还没有发布的文章!渲染的模板为 index.html
访问的分类有文章,则响应中应该包含系列关键的模板变量,post_list、is_paginated、page_obj,post_list 文章数量为1,因为我们的测试数据中这个分类下只有一篇文章,post_list 是一个 queryset,预期是该分类下的全部文章,时间倒序排序。
其它的 TagViewTestCase 等测试类似,请自行参照代码分析。
博客文章详情视图的逻辑更加复杂一点,所以测试用例也更多,主要需要测试的点有:
访问不存在文章,返回404。
文章每被访问一次,访问量 views 加一。
文章内容被 markdown 渲染,并生成了目录。
测试代码如下:
class PostDetailViewTestCase(BlogDataTestCase): def setUp(self): super().setUp() self.md_post = Post.objects.create( title='Markdown 测试标题', body='# 标题', category=self.cate1, author=self.user, ) self.url = reverse('blog:detail', kwargs={'pk': self.md_post.pk}) def test_good_view(self): response = self.client.get(self.url) self.assertEqual(response.status_code, 200) self.assertTemplateUsed('blog/detail.html') self.assertContains(response, self.md_post.title) self.assertIn('post', response.context) def test_visit_a_nonexistent_post(self): url = reverse('blog:detail', kwargs={'pk': 100}) response = self.client.get(url) self.assertEqual(response.status_code, 404) def test_increase_views(self): self.client.get(self.url) self.md_post.refresh_from_db() self.assertEqual(self.md_post.views, 1) self.client.get(self.url) self.md_post.refresh_from_db() self.assertEqual(self.md_post.views, 2) def test_markdownify_post_body_and_set_toc(self): response = self.client.get(self.url) self.assertContains(response, '文章目录') self.assertContains(response, self.md_post.title) post_template_var = response.context['post'] self.assertHTMLEqual(post_template_var.body_html, "<h1>标题</h1>") self.assertHTMLEqual(post_template_var.toc, '<li><a href="#标题">标题</li>')接下来是测试 admin 添加文章和 rss 订阅内容,这一块比较简单,因为大部分都是 django 的逻辑,django 已经为我们进行了测试,我们需要测试的只是自定义的部分,确保自定义的逻辑按照预期的定义运行,并且得到了预期的结果。
对于 admin,预期的结果就是发布文章后,的确自动填充了 author:
class AdminTestCase(BlogDataTestCase): def setUp(self): super().setUp() self.url = reverse('admin:blog_post_add') def test_set_author_after_publishing_the_post(self): data = { 'title': '测试标题', 'body': '测试内容', 'category': self.cate1.pk, } self.client.login(username=self.user.username, password='admin') response = self.client.post(self.url, data=data) self.assertEqual(response.status_code, 302) post = Post.objects.all().latest('created_time') self.assertEqual(post.author, self.user) self.assertEqual(post.title, data.get('title')) self.assertEqual(post.category, self.cate1)