Вопрос

I am newbie and trying to make my Unit Test pass but having problems with DateTimeField.

In my settings, I have USE_TZ = True and TIME_ZONE set.

Using MongoDb.

First the test is giving me an error complaining about comparing offset-naive and offset-aware. Changed auto_now_add=True to datetime.datetime.utcnow().replace(tzinfo=utc))

I Still couldn't get the right time and date to my TIME_ZONE.

After I put these in my Database (settings.py)

'OPTIONS' : {
    'tz_aware' : True, 
}

Now I can change my TIME_ZONE and the time and date shows my localtime, not utc.

But when I run a test model:

nf.data_emissao = timezone.now()
...

#check if the nf is in database
lista_nfse = Nfse.objects.all()
self.assertEquals(lista_nfse.count(), 1)

nfse_no_banco = lista_nfse[0]
...
self.assertEquals( nfse_no_banco.data_emissao, nf.data_emissao)

My test fails:

AssertionError: datetime.datetime(2013, 8, 10, 2, 49, 59, 391000, tzinfo=
<bson.tz_util.FixedOffset object at 0x2bdd1d0>) != datetime.datetime(2013, 8, 10, 2, 49, 59, 
391122, tzinfo=<UTC>)

I see the diff between 391000 and 391122 but don't know how to fix that.

Это было полезно?

Решение

The problem look to be that you are comparing two values that were assigned with the time 'now' at two different points in time.

Writing unit tests to work with automatically generated dates is always tricky when trying to assert exact date values due to the ever changing nature of time. However, there are a couple of techniques that can be used to help create reliable tests in these scenarios:

  • If you are trying to assert 'nfse_no_banco.data_emissao contains the time now', instead of trying to assert an exact value you could assert that the time field value falls within the last x milliseconds of time. This allows you to gain a fair level of confidence that the value in the field was 'now' at the time it was assigned, but the downsides are (a) your test could unreliable if the execution time of the test happens to take longer than x milliseconds and (b) the test would return a false positive if for some reason the value was incorrectly assigned a time very close to now due to a programming error (which is highly unlikely).

  • You can monkey-patch datetime.datetime.utcnow to your own version of the method that returns a pre-set value for testing purposes, and then assert that value was assigned to nfse_no_banco.data_emissao. The downside is that it adds a little complexity to your test setup and teardown. However, it should result in a good test if the goal of your assertion is to verify that the field has been assigned the time now.

  • You can simply assert that the value of the field is not null (using self.assertNotNull(nfse_no_banco.data_emissao)) - although this is a much weaker assertion, in cases where you are using some framework functionality (such as auto_now_add=True in Django) then often this will suffice - of course the major upside to this test is it's very simple and reliable.

The best approach really depends on what you are trying to assert. From your question it appears that you are really trying to assert that nfse_no_banco.data_emissao was assigned the time now, and you are doing this yourself (rather than relying on a framework to do it for you), and therefore the second approach would make most sense.

Below is pseudo-code showing how you could do this in your test:

# Create a constant with a fixed value for utcnow
NOW = datetime.datetime.utcnow()

# Define a test method to replace datetime.datetime.utcnow
def utcnow_fixed_value():
    return NOW

class MyTest(TestCase):

    def setUp(self):
        # Replace the real version of utcnow with our test version
        self.real_utcnow = datetime.datetime.utcnow
        datetime.datetime.utcnow = utcnow_fixed_value

    def tearDown(self):
        # Undo the monkey patch and replace the real version of utcnow
        datetime.datetime.utcnow = self.real_utcnow

    def test_value_is_now(self):
        lista_nfse = Nfse.objects.all()
        self.assertEquals(lista_nfse.count(), 1)

        nfse_no_banco = lista_nfse[0]
        ...
        self.assertEquals(NOW, nfse_no_banco.data_emissao)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top