代码之家  ›  专栏  ›  技术社区  ›  TimJ

单元测试Django模型保存函数

  •  2
  • TimJ  · 技术社区  · 6 年前

    我正在创建测试,以检查自定义校准模型保存功能是否会更新资产记录(外键),如果它是资产的最新校准记录。save函数在live dev中的性能与预期完全一致;生产服务器,甚至在django shell中,但在测试期间似乎失败了。。。

    模型。py公司

    class Asset(models.Model):
        ...
        requires_calibration = models.BooleanField()
        passed_calibration = models.BooleanField(default=False)
        calibration_date_prev = models.DateField(null=True, blank=True)
        calibration_date_next = models.DateField(null=True, blank=True)
    
    
    class CalibrationRecord(models.Model):
        calibration_record_id = models.AutoField(primary_key=True)
        asset = models.ForeignKey(
                                  "myapp.Asset",
                                  on_delete=models.CASCADE,
                                  limit_choices_to={"requires_calibration": True}
                                  )
        calibration_date = models.DateField(default=timezone.now)
        calibration_date_next = models.DateField(null=True, blank=True)
        calibration_outcome = models.CharField(max_length=10, default="Pass")
    
        def save(self, *args, **kwargs):
    
            super(CalibrationRecord, self).save(*args, **kwargs)
    
            # Check if this is the latest calibration record for any asset, if so update asset.calibration_dates and status
            latest_asset_calibration = CalibrationRecord.objects.filter(asset=self.asset.pk).order_by(
                "-calibration_date", "-calibration_record_id")[0]
    
            if self.pk == latest_asset_calibration.pk:
    
                Asset.objects.filter(pk=self.asset.pk).update(calibration_date_prev=self.calibration_date)
    
                if self.calibration_date_next:
                    Asset.objects.filter(pk=self.asset.pk).update(calibration_date_next=self.calibration_date_next)
                else:
                    Asset.objects.filter(pk=self.asset.pk).update(calibration_date_next=None)
    
                if self.calibration_outcome == "Pass":
                    Asset.objects.filter(pk=self.asset.pk).update(passed_calibration=True)
                else:
                    Asset.objects.filter(pk=self.asset.pk).update(passed_calibration=False)
    

    tests\u模型。py示例失败测试

    class CalibrationRecordTests(TestCase):
        def test_calibration_record_updates_asset_cal_date_prev(self):
            """
            All calibration records should update related Asset record's "calibration_date_prev" to calibration_date
            """
            asset1 = Asset.objects.create(asset_description="Test Asset 2", requires_calibration=True)
            self.assertIsNone(asset1.calibration_date_prev)
            cal = CalibrationRecord.objects.create(asset=asset1, calibration_description="Test Calibration 2", calibration_date=timezone.now())
            self.assertEqual(cal.calibration_date, asset1.calibration_date_prev)
    

    错误日志

    ======================================================================
    FAIL: test_calibration_record_updates_asset_cal_date_prev (assetregister.tests_models.CalibrationRecordTests)
    ----------------------------------------------------------------------
    Traceback (most recent call last):
      File "C:\[path]\app\tests_models.py", line 159, in test_calibration_record_updates_asset_cal_date_prev
    self.assertEqual(cal.calibration_date, asset1.calibration_date_prev)
    AssertionError: datetime.datetime(2018, 2, 26, 12, 26, 34, 457513, tzinfo=<UTC>) != None
    ======================================================================
    

    与此自定义校准记录保存功能相关的所有测试似乎都失败了,因为相关资产记录没有在应该更新的时候更新。

    你知道为什么这在开发和生产过程中有效,但在测试过程中无效吗?

    即使。create()方法应自动执行。save()之后,我甚至试着做一本手册。创建校准记录后保存(),但似乎仍然失败。

    2 回复  |  直到 6 年前
        1
  •  6
  •   TimJ    6 年前

    解决了的!

    自定义保存函数可以正确更新数据库,但不能更新正在测试的模型实例!需要 刷新 通过再次调用模型实例来获取任何更新,方法如下 [model].objects.get()

    例如。:

        asset = Asset.objects.create(asset_description="Test Asset 2", requires_calibration=True)
        self.assertIsNone(asset.calibration_date_prev)
        CalibrationRecord.objects.create(asset=asset, calibration_description="Test Calibration 2",
                                         calibration_date=timezone.now())
        cal = CalibrationRecord.objects.get(calibration_description="Test Calibration 2")
        asset = Asset.objects.get(asset_description="Test Asset 2")
        self.assertEqual(cal.calibration_date, asset.calibration_date_prev)
    
        2
  •  1
  •   Cowen Shears    2 年前

    如果你发现自己在这里,最好用 Model.refresh_from_db(using=None, fields=None) . 请参见 Django documentation

    同时签出 Reload django object from database