编写 Django 应用单元测试 (4)

reverse('admin:blog_post_add') 获取 admin 管理添加博客文章的 URL,django admin 添加文章的视图函数名为 admin:blog_post_add,一般 admin 后台操作模型的视图函数命名规则是 <app_label>_<model_name>_<action>。

self.client.login(username=self.user.username, password='admin') 登录用户,相当于后台登录管理员账户。

self.client.post(self.url, data=data) ,向添加文章的 url 发起 post 请求,post 的数据为需要发布的文章内容,只指定了 title,body和分类。

接着我们进行一系列断言,确认是否正确创建了文章。

RSS 测试也类似,我们期待的是,它返回的内容中的确包含了全部文章的内容:

class RSSTestCase(BlogDataTestCase): def setUp(self): super().setUp() self.url = reverse('rss') def test_rss_subscription_content(self): response = self.client.get(self.url) self.assertContains(response, AllPostsRssFeed.title) self.assertContains(response, AllPostsRssFeed.description) self.assertContains(response, self.post1.title) self.assertContains(response, self.post2.title) self.assertContains(response, '[%s] %s' % (self.post1.category, self.post1.title)) self.assertContains(response, '[%s] %s' % (self.post2.category, self.post2.title)) self.assertContains(response, self.post1.body) self.assertContains(response, self.post2.body) 测试模板标签

这里测试的核心内容是,模板中 {% templatetag %} 被渲染成了正确的 HTML 内容。你可以看到测试代码中对应的代码:

context = Context(show_recent_posts(self.ctx)) template = Template( '{% load blog_extras %}' '{% show_recent_posts %}' ) expected_html = template.render(context)

注意模板标签本质上是一个 Python 函数,第一句代码中我们直接调用了这个函数,由于它需要接受一个 Context 类型的标量,因此我们构造了一个空的 context 给它,调用它将返回需要的上下文变量,然后我们构造了一个需要的上下文变量。

接着我们构造了一个模板对象。

最后我们使用构造的上下文去渲染了这个模板。

我们调用了模板引擎的底层 API 来渲染模板,视图函数会渲染模板,返回响应,但是我们没有看到这个过程,是因为 django 帮我们在背后的调用了这个过程。

全部模板引擎的测试套路都是一样,构造需要的上下文,构造模板,使用上下文渲染模板,断言渲染的模板内容符合预期。以为例:

def test_show_recent_posts_with_posts(self): post = Post.objects.create( title='测试标题', body='测试内容', category=self.cate, author=self.user, ) context = Context(show_recent_posts(self.ctx)) template = Template( '{% load blog_extras %}' '{% show_recent_posts %}' ) expected_html = template.render(context) self.assertInHTML('<h3>最新文章</h3>', expected_html) self.assertInHTML('<a href="http://www.likecs.com/{}">{}</a>'.format(post.get_absolute_url(), post.title), expected_html)

这个模板标签对应侧边栏的最新文章版块。我们进行了2处关键性的内容断言。一个是包含最新文章版块标题,一个是内容中含有文章标题的超链接。

测试辅助方法和类

我们的博客中只自定义了关键词高亮的一个逻辑。

class HighlighterTestCase(TestCase): def test_highlight(self): document = "这是一个比较长的标题,用于测试关键词高亮但不被截断。" highlighter = Highlighter("标题") expected = '这是一个比较长的<span>标题</span>,用于测试关键词高亮但不被截断。' self.assertEqual(highlighter.highlight(document), expected) highlighter = Highlighter("关键词高亮") expected = '这是一个比较长的标题,用于测试<span>关键词高亮</span>但不被截断。' self.assertEqual(highlighter.highlight(document), expected)

这里 Highlighter 实例化时接收搜索关键词作为参数,然后 highlight 将搜索结果中关键词包裹上 span 标签。

Highlighter 事实上 haystack 为我们提供的类,我们只是定义了 highlight 方法的逻辑。我们又是如何知道 highlight 方法的逻辑呢?如何进行测试呢?

我是看源码,大致了解了 Highlighter 类的实现逻辑,然后我从 haystack 的测试用例中找到了 highlight 的测试方法。

所以,有时候不要惧怕去看源代码,Python 世界里一切都是开源的,源代码也没有什么神秘的地方,都是人写的,别人能写出来,你学习后也一样能写出来。单元测试的代码一般比较冗长重复,但目的也十分明确,而且大都以顺序逻辑组织,代码自成文档,非常好读。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpxwfd.html