简体   繁体   中英

SQLite3 not catching username that's too long

I recently modified my Django project's settings to that it uses SQLite3 when I run tests instead of PostgreSQL so that my tests will run faster. However, once I did that, one of my negative unit tests that checks to verify that Django will throw an error if I try to create a user whose username exceeds 30 characters started failing. Up until this time, the test had always passed.

If I run the following test using PostgreSQL, an exception (specifically a DatabaseError) is raised and the test passes. However, if I use SQLite3 instead, no exception is raised and the test fails. I double-checked the SQLite3 auth_user schema and confirmed username is a varchar(30) field. Has anyone else experienced this? Thanks.

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"

In addition to Zuko's answer, I would contest that your unit test may not be doing the correct thing.

It appears to be a common misconception that model validation occurs before it is saved. See the documentation for Model validation .

What you're doing is expecting the max_length parameter to your model field to be honoured without going through the validation functions. When you use ModelForms , the form will ensure that model validation is called and you will get a ValidationError .

The same applies for other constraints such as the is_blank option to CharField types. As far as I know, this validation can only occur in Python land since there is no available constraint you can apply at the database level to check whether a field is blank.

There are a number of other questions on StackOverflow relating this this issue which will explain how you might force validation in all circumstances, eg this answer

Alternativly, have your unit test call the full_clean() instance method to check that all validation constraints have been met.

I believe that the reason for this is that sqlite3 converts all varchar data types to the text data type under the hood. This is why the DBMS won't catch any values that exceed your limit. The documentation is a little bit unclear in this regard, but I ran into this problem before and from the documentation, that was the best answer I could come up with. So basically,

CREATE TABLE A(name varchar(30))

Will end up being identical to:

CREATE TABLE A(name text)

Check out the documentation here (section 2.2): http://www.sqlite.org/datatype3.html

A test you can do to see that this is just the functionality of the DBMS:

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

As you can see, there are no errors, and no truncation.

Hope that helps,

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM