Django - 即使 link 有效,测试也会失败
Django - Test fails even though the link works
我发现了一个用 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 dispatcher"。每次需要自动递增 id 时,分配一个并递增计数器的某种例程。但请注意,如果您稍后删除该对象并创建一个新对象,您将 不是 "reuse" 标识符,而只是简单地使用下一个(某些数据库将计算重新启动时的最大值 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": <b>self.board.pk</b>})
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 将构建不同的查询在新的数据库系统上工作)。通过做出这样的假设,您最终将“将自己锁定在”到一个特定的体系结构中,如果稍后您的应用程序的需求发生变化,这可能是危险的,而不同的体系结构更适合这些需求.
我发现了一个用 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 dispatcher"。每次需要自动递增 id 时,分配一个并递增计数器的某种例程。但请注意,如果您稍后删除该对象并创建一个新对象,您将 不是 "reuse" 标识符,而只是简单地使用下一个(某些数据库将计算重新启动时的最大值 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": <b>self.board.pk</b>})
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 将构建不同的查询在新的数据库系统上工作)。通过做出这样的假设,您最终将“将自己锁定在”到一个特定的体系结构中,如果稍后您的应用程序的需求发生变化,这可能是危险的,而不同的体系结构更适合这些需求.