Django - 即使链接有效,测试也会失败



我找到了一个用Django-1.11编写的很棒的教程。但是我决定使用当前版本(2.0.5(并尝试改编教程。如果我成功了,我想在之后提供本教程的更新版本。

更改了一些不推荐使用的内容,我已经在官方 Django 文档的帮助下做得很好。但是在编写一些测试时,我遇到了困难。

我不明白为什么我会收到这个404 != 200错误。

views.py

# ...
def board_topics(request, pk):
board = get_object_or_404(Board, pk=pk)
return render(request, "topics.html", {"board": board})

urls.py

# ...
urlpatterns = [
path("boards/<int:pk>/", views.board_topics, name="board_topics"),
path("home/", views.home, name="home"),
path("admin/", admin.site.urls),
]

tests.py

# ...
class BoardTopicsTests(TestCase):
def setUp(self):
self.board = Board.objects.create(
name="Django", description="Django discussion board"
)
# ...
def test_board_topics_view_contains_link_back_to_homepage(self):
board_topics_url = reverse("board_topics", kwargs={"pk": 1})
response = self.client.get(board_topics_url)
homepage_url = reverse("home")
self.assertContains(
response, 'href="{0}"'.format(homepage_url)
)

追踪

FAIL: test_board_topics_view_contains_link_back_to_homepage (boards.tests.BoardTopicsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/.../boards/tests.py", line 52, in test_board_topics_view_contains_link_back_to_homepage
self.assertContains(response, 'href="{0}"'.format(homepage_url))
...
AssertionError: 404 != 200 : 
Couldn't retrieve content: Response code was 404 (expected 200)
----------------------------------------------------------------------
Ran 7 tests in 0.038s
FAILED (failures=1)

我想知道为什么我会收到此错误,尽管我可以调用视图。我是否正确编写了此测试?

该错误可能是因为没有主键pk=1的元素引起的。数据库通常会在内存中存储一个"id 调度程序"。某种例程,每次需要自动递增 id 时,都会分发一个并递增计数器。但请注意,如果您稍后删除该对象并创建一个新对象,则不会"重用"标识符,而只需获取下一个标识符(某些数据库将在重新启动时计算最大id,并继续从该标识符计数(。

无论数据库实际调度主键的方式如何,您都无法控制该过程,因此对此做出假设是不安全的。

因此,最好获取存储Board对象的pk属性:

class BoardTopicsTests(TestCase):
def setUp(self):
self.board = Board.objects.create(
name="Django", description="Django discussion board"
)
# ...
def test_board_topics_view_contains_link_back_to_homepage(self):
board_topics_url = reverse("board_topics", kwargs={"pk":self.board.pk})
response = self.client.get(board_topics_url)
homepage_url = reverse("home")
self.assertContains(response, 'href="{0}"'.format(homepage_url))

当您运行pytest(或其他测试工具(时,它将在当前测试用例之前和之后运行测试,因此您并不真正知道 id 调度程序到达此特定测试用例时的状态。

以上是">对后端做出太多假设"的特例。Django 背后的一个想法是拥有一个例如数据库不变的 ORM(在某种程度上(。所以这意味着你不应该假设一个特定的数据库系统将如何工作,因为Django的目的是轻松地将应用程序从一个数据库系统迁移到另一个数据库系统,并保持所有代码不变(例如,Django ORM将构建不同的查询,这些查询适用于新的数据库系统(。通过做出这样的假设,您最终会将自己"锁定"到特定的体系结构中,如果以后应用程序的需求发生变化,并且不同的体系结构更适合这些需求,则可能会很危险。

最新更新