text: import unittest
  
  from django.test import TestCase
  
  from ..config import HARD_DELETE, SOFT_DELETE
  
  
  class SafeDeleteTestCase(TestCase):
  
      def assertDelete(self, instance, expected_results, expected_output=None, force_policy=None, save=True):
          """Assert specific specific expected results before delete, after delete and after save.
  
          Example of expected_results, see SafeDeleteTestCase.assertSoftDelete.
  
          Args:
              instance: Model instance.
              expected_results: Specific expected results before delete, after delete and after save.
              expected_output: Specific expected output to delete call, None if verification should be more generic. (default: {None}).
              force_policy: Specific policy to force, None if no policy forced. (default: {None})
              save: Whether to test the Model.save() restoration. (default: {True})
          """
          model = instance.__class__
  
          self.assertEqual(
              model.objects.count(),
              expected_results['before_delete']['all']
          )
          self.assertEqual(
              model.all_objects.count(),
              expected_results['before_delete']['all_with_deleted']
          )
  
          if force_policy is not None:
              output = instance.delete(force_policy=force_policy)
          else:
              output = instance.delete()
  
          if expected_output:
              self.assertEqual(output, expected_output)
          else:
              self.assertGreaterEqual(output[0], 1)
              self.assertGreaterEqual(output[1].items(), {instance._meta.label: 1}.items())
  
          self.assertEqual(
              model.objects.count(),
              expected_results['after_delete']['all']
          )
          self.assertEqual(
              model.all_objects.count(),
              expected_results['after_delete']['all_with_deleted']
          )
  
          if not save:
              return
  
          # If there is no after_save in the expected results, then we assume
          # that Model.save will give a DoesNotExist exception because it was
          # a hard delete. So we test whether it was a hard delete.
          if 'after_save' not in expected_results:
              self.assertRaises(
                  model.DoesNotExist,
                  instance.refresh_from_db
              )
          else:
              instance.save()
              self.assertEqual(
                  model.objects.count(),
                  expected_results['after_save']['all']
              )
              self.assertEqual(
                  model.all_objects.count(),
                  expected_results['after_save']['all_with_deleted']
              )
  
      def assertSoftDelete(self, instance, force=False, **kwargs):
          """Assert whether the given model instance can be soft deleted.
  
          Args:
              instance: Model instance.
              force: Whether to force the soft delete policy. (default: {False})
          """
          self.assertDelete(
              instance=instance,
              expected_results={
                  'before_delete': {
                      'all': 1,
                      'all_with_deleted': 1
                  },
                  'after_delete': {
                      'all': 0,
                      'all_with_deleted': 1
                  },
                  # Saving a soft deleted model should reinstate it.
                  'after_save': {
                      'all': 1,
                      'all_with_deleted': 1
                  },
              },
              force_policy=SOFT_DELETE if force else None,
              **kwargs
          )
  
      def assertHardDelete(self, instance, force=False, **kwargs):
          """Assert whether the given model instance can be hard deleted.
  
          Args:
              instance: Model instance.
              force: Whether to force the soft delete policy. (default: {False})
          """
          self.assertDelete(
              instance=instance,
              expected_results={
                  'before_delete': {
                      'all': 1,
                      'all_with_deleted': 1
                  },
                  'after_delete': {
                      'all': 0,
                      'all_with_deleted': 0
                  },
              },
              force_policy=HARD_DELETE if force else None,
              **kwargs
          )
  
  
  class SafeDeleteForceTestCase(SafeDeleteTestCase):
  
      def check_skip(self):
          """Skip tests that should only run when inherited."""
          if self.__class__ == SafeDeleteForceTestCase:
              raise unittest.SkipTest(
                  "Only SafeDeleteForceTestCase subclasses can have tests that use "
                  "SafeDeleteForceTestCase.instance."
              )
  
      def test_harddelete_force(self):
          """Test whether the subclasses their instances can also be force hard deleted."""
          self.check_skip()
          self.assertHardDelete(self.instance, force=True)
  
      def test_softdelete_force(self):
          """Test whether the subclasses their instances can also be force soft deleted."""
          self.check_skip()
          self.assertSoftDelete(self.instance, force=True)
  