1

我最近修改了我的 Django 项目的设置,使其在我运行测试而不是 PostgreSQL 时使用 SQLite3,以便我的测试运行得更快。但是,一旦我这样做了,如果我尝试创建一个用户名超过 30 个字符的用户,我的一个否定单元测试会检查以验证 Django 是否会抛出错误。直到这个时候,测试总是通过。

如果我使用 PostgreSQL 运行以下测试,则会引发异常(特别是 DatabaseError)并且测试通过。但是,如果我改用 SQLite3,则不会引发异常并且测试失败。我仔细检查了 SQLite3 auth_user 模式并确认用户名是 varchar(30) 字段。有没有其他人经历过这个?谢谢。

from django.test import TestCase
from django.contrib.auth.models import User

class SimpleTest(TestCase):
    def test_simple(self):
        exception_raised = True  # Exception should be raised since username > 30 chars
        try:
            user = User.objects.create_user(username='testusertestusertestusertestuser')
        except Exception as e:
            exception_raised = False
        assert not exception_raised, "Exception wasn't raised"
4

2 回答 2

1

除了 Zuko 的回答之外,我认为您的单元测试可能没有做正确的事情。

模型验证在保存之前发生似乎是一种常见的误解。请参阅模型验证文档。

您正在做的是期望max_length模型字段的参数在不通过验证功能的情况下得到兑现。当您使用ModelForms时,表单将确保调用模型验证并且您将获得一个ValidationError.

这同样适用于其他约束,例如类型的is_blank选项CharField。据我所知,这种验证只能在 Python 领域进行,因为没有可用的约束可以在数据库级别应用来检查字段是否为空白。

StackOverflow 上还有许多与此问题相关的其他问题,这些问题将解释您如何在所有情况下强制验证,例如这个答案

或者,让您的单元测试调用full_clean()实例方法以检查是否满足所有验证约束。

于 2013-02-01T01:51:04.263 回答
0

我相信这样做的原因是 sqlite3 在后台将所有 varchar 数据类型转换为 text 数据类型。这就是 DBMS 不会捕获任何超出限制的值的原因。文档在这方面有点不清楚,但是我在文档之前和文档中都遇到了这个问题,这是我能想到的最好的答案。所以基本上,

CREATE TABLE A(name varchar(30))

最终将与以下内容相同:

CREATE TABLE A(name text)

在此处查看文档(第 2.2 节):http ://www.sqlite.org/datatype3.html

你可以做一个测试,看看这只是 DBMS 的功能:

sqlite> create table A(name varchar(2));
sqlite> insert into A values("hello world");
sqlite> select * from A;
hello world

如您所见,没有错误,也没有截断。

希望有帮助,

于 2013-01-31T23:32:06.493 回答