class TestPanoptesPollingPluginRunner(unittest.TestCase): @patch('redis.StrictRedis', panoptes_mock_redis_strict_client) @patch('kazoo.client.KazooClient', panoptes_mock_kazoo_client) def setUp(self): self.my_dir, self.panoptes_test_conf_file = get_test_conf_file() self._panoptes_resource = PanoptesResource( resource_site="test", resource_class="test", resource_subclass="test", resource_type="test", resource_id="test", resource_endpoint="test", resource_creation_timestamp=_TIMESTAMP, resource_plugin="test") self._panoptes_context = PanoptesContext( self.panoptes_test_conf_file, key_value_store_class_list=[ PanoptesTestKeyValueStore, PanoptesResourcesKeyValueStore, PanoptesPollingPluginKeyValueStore, PanoptesSecretsStore, PanoptesPollingPluginAgentKeyValueStore, PanoptesDiscoveryPluginAgentKeyValueStore, PanoptesDiscoveryPluginKeyValueStore ], create_message_producer=False, async_message_producer=False, create_zookeeper_client=True) self._runner_class = PanoptesPluginWithEnrichmentRunner self._log_capture = LogCapture( attributes=TestPanoptesPluginRunner.extract) def tearDown(self): self._log_capture.uninstall() def tearDown(self): self._log_capture.uninstall() @patch('yahoo_panoptes.framework.metrics.time') @patch( 'yahoo_panoptes.framework.context.PanoptesContext._get_message_producer' ) @patch('yahoo_panoptes.framework.context.PanoptesContext.message_producer', new_callable=PropertyMock) @patch( 'yahoo_panoptes.polling.polling_plugin_agent.PanoptesPollingTaskContext' ) @patch( 'yahoo_panoptes.framework.resources.PanoptesResourceStore.get_resource' ) def test_polling_plugin_agent(self, resource, panoptes_context, message_producer, message_producer_property, time): producer = MockPanoptesMessageProducer() time.return_value = 1 message_producer.return_value = producer message_producer_property.return_value = producer resource.return_value = self._panoptes_resource panoptes_context.return_value = self._panoptes_context polling_plugin_task('Test Polling Plugin', 'polling') log_prefix = '[Test Polling Plugin] [plugin|test|site|test|class|test|' \ 'subclass|test|type|test|id|test|endpoint|test]' self._log_capture.check_present( ('panoptes.tests.test_runner', 'INFO', 'Attempting to execute plugin "Test Polling Plugin"'), ('panoptes.tests.test_runner', 'DEBUG', 'Loaded plugin "Test Polling Plugin", ' 'version "0.1" of type "polling", category "polling"'), ('panoptes.tests.test_runner', 'DEBUG', 'Loaded plugin "Test Polling Plugin 2", ' 'version "0.1" of type "polling", category "polling"'), ('panoptes.tests.test_runner', 'ERROR', 'No enrichment data found on KV store for plugin Test' ' Polling Plugin resource test namespace test using key test'), ('panoptes.tests.test_runner', 'DEBUG', 'Successfully created PanoptesEnrichmentCache enrichment_data ' '{} for plugin Test Polling Plugin'), ('panoptes.tests.test_runner', 'DEBUG', 'Attempting to get lock for plugin "Test Polling Plugin", ' 'with lock path and identifier in seconds'), ('panoptes.tests.test_runner', 'INFO', '{} Acquired lock'.format(log_prefix)), ('panoptes.tests.test_runner', 'INFO', '{} Plugin returned a result set with 1 members'.format( log_prefix)), ('panoptes.tests.test_runner', 'INFO', '{} Callback function ran in seconds'.format(log_prefix)), ('panoptes.tests.test_runner', 'INFO', '{} Ran in seconds'.format(log_prefix)), ('panoptes.tests.test_runner', 'INFO', '{} Released lock'.format(log_prefix)), ('panoptes.tests.test_runner', 'INFO', '{} GC took seconds. There are garbage objects.'.format( log_prefix)), ('panoptes.tests.test_runner', 'DEBUG', 'Deleting module: yapsy_loaded_plugin_Test_Polling_Plugin'), ('panoptes.tests.test_runner', 'DEBUG', 'Deleting module: yapsy_loaded_plugin_Test_Polling_Plugin'), ('panoptes.tests.test_runner', 'DEBUG', 'Deleting module: ' 'yapsy_loaded_plugin_Test_Polling_Plugin_Second_Instance'), order_matters=False) kafka_push_log = { "metrics_group_type": "Test", "metrics_group_interval": 60, "metrics_group_creation_timestamp": 1, "metrics_group_schema_version": "0.2", "resource": { "resource_site": "test", "resource_class": "test", "resource_subclass": "test", "resource_type": "test", "resource_id": "test", "resource_endpoint": "test", "resource_metadata": { "_resource_ttl": "604800" }, "resource_creation_timestamp": 1.0, "resource_plugin": "test" }, "metrics": [{ "metric_creation_timestamp": 1, "metric_name": "test", "metric_value": 0.0, "metric_type": "gauge" }], "dimensions": [] } # Timestamps need to be removed to check Panoptes Metrics metric_groups_seen = 0 for line in self._log_capture.actual(): _, _, log = line if 'resource_creation_timestamp' in log: log = re.sub(r"resource_creation_timestamp\": \d+\.\d+,", "resource_creation_timestamp\": 1.0,", log) resource_match = re.search(r'{.*}', log) if resource_match is not None: self.assertEqual( ordered(json.loads(resource_match.group(0))), ordered(kafka_push_log)) if log.startswith('Sent metric group'): metric_groups_seen += 1 if log.startswith('Going to send metric group'): metric_groups_seen += 1 self.assertEqual(metric_groups_seen, 2)
def check_contain(log_capture: LogCapture, expected: tuple) -> bool: return expected in set(log_capture.actual())
class TestProcessPayments(CacheResetMixin, TestCase): """Test process_payments command.""" def setUp(self): super().setUp() self.tempdir = TempDirectory() self.account = BankAccount(account_number='123456/7890', currency='CZK') self.account.save() payment = get_payment(identifier='PAYMENT_1', account=self.account, state=PaymentState.READY_TO_PROCESS) payment.save() self.log_handler = LogCapture( 'django_pain.management.commands.process_payments', propagate=False) def tearDown(self): self.log_handler.uninstall() self.tempdir.cleanup() def _test_non_existing_account(self, param_name): """ Test non existing account. param_name should contain either '--include-accounts' or '--exclude-accounts' """ BankAccount.objects.create(account_number='987654/3210', currency='CZK') with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): out = StringIO() err = StringIO() with self.assertRaises(CommandError): call_command('process_payments', param_name, 'xxxxxx/xxxx,yyyyyy/yyyy,987654/3210', stdout=out, stderr=err) self.assertEqual(out.getvalue(), '') self.assertEqual(err.getvalue(), '') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'ERROR', 'Following accounts do not exist: xxxxxx/xxxx, yyyyyy/yyyy. Terminating.' ), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_payments_processed(self): """Test processed payments.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual(BankPayment.objects.values_list( 'identifier', 'account', 'state', 'processor'), [('PAYMENT_1', self.account.pk, PaymentState.PROCESSED, 'dummy')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'True objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 1 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyFalsePaymentProcessor' }) def test_payments_deferred(self): """Test deferred payments.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual( BankPayment.objects.values_list('identifier', 'account', 'state', 'processor'), [('PAYMENT_1', self.account.pk, PaymentState.DEFERRED, '')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, '') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 1 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 1 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTrueErrorPaymentProcessor' }) def test_payments_processed_with_error(self): """Test processed payments with processing error.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual( BankPayment.objects.values_list('identifier', 'account', 'state', 'processor', 'processing_error'), [('PAYMENT_1', self.account.pk, PaymentState.PROCESSED, 'dummy', PaymentProcessingError.DUPLICITY)], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'Dummy objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 1 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyFalseErrorPaymentProcessor' }) def test_payments_deferred_with_error(self): """Test deferred payments with processing error.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual( BankPayment.objects.values_list('identifier', 'account', 'state', 'processor', 'processing_error'), [('PAYMENT_1', self.account.pk, PaymentState.DEFERRED, 'dummy', PaymentProcessingError.DUPLICITY)], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'Dummy objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 1 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Saving payment %s as DEFERRED with error PaymentProcessingError.DUPLICITY.' % BankPayment.objects.first().uuid), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings(PAIN_PROCESSORS=OrderedDict([ ('dummy_false', 'django_pain.tests.commands.test_process_payments.DummyFalsePaymentProcessor' ), ('dummy_true', 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' ), ])) def test_payments_from_to(self): """Test processed payments.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments', '--from', '2017-01-01 00:00', '--to', '2017-01-02 00:00') self.assertQuerysetEqual(BankPayment.objects.values_list( 'identifier', 'account', 'state', 'processor'), [('PAYMENT_1', self.account.pk, PaymentState.READY_TO_PROCESS, '')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, '') def test_invalid_date_raises_exception(self): with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): with self.assertRaises(CommandError): call_command('process_payments', '--from', '2017-01-32 00:00', '--to', '2017-02-01 00:00') with self.assertRaises(CommandError): call_command('process_payments', '--from', 'not a date', '--to', '2017-02-01 00:00') with self.assertRaises(CommandError): call_command('process_payments', '--from', '2017-01-01 00:00', '--to', '2017-01-32 00:00') with self.assertRaises(CommandError): call_command('process_payments', '--from', '2017-01-01 00:00', '--to', 'not a date') def test_lock(self): """Test process payments lock.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): lock = open(SETTINGS.process_payments_lock_file, 'a') fcntl.flock(lock, fcntl.LOCK_EX | fcntl.LOCK_NB) out = StringIO() err = StringIO() call_command('process_payments', '--no-color', stdout=out, stderr=err) self.assertEqual(out.getvalue(), '') self.assertEqual( err.getvalue(), 'Command process_payments is already running. Terminating.\n') self.assertQuerysetEqual(BankPayment.objects.values_list( 'identifier', 'account', 'state', 'processor'), [('PAYMENT_1', self.account.pk, PaymentState.READY_TO_PROCESS, '')], transform=tuple, ordered=False) self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'WARNING', 'Command already running. Terminating.')) def test_invalid_lock(self): """Test process payments with invalid lock file.""" with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): os.mkdir(SETTINGS.process_payments_lock_file, mode=0o0) out = StringIO() err = StringIO() with self.assertRaisesRegexp( CommandError, r'^Error occured while opening lockfile .*/test.lock:.*Is a ' r'directory: .*\. Terminating\.$'): call_command('process_payments', '--no-color', stdout=out, stderr=err) self.assertEqual(out.getvalue(), '') self.assertEqual(err.getvalue(), '') self.assertEqual(len(self.log_handler.actual()), 2) self.assertEqual( self.log_handler.actual()[0], ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ) self.assertEqual( self.log_handler.actual()[1][:2], ('django_pain.management.commands.process_payments', 'ERROR')) self.assertRegex( self.log_handler.actual()[1][2], r'^Error occured while opening lockfile .*/test.lock:.*Is a directory.*Terminating\.$' ) os.chmod(SETTINGS.process_payments_lock_file, 0o755) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_exclusion_in_payment_processing(self): """Test excluding accounts from payment processing""" account2 = BankAccount(account_number='987654/3210', currency='CZK') account2.save() get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS).save() get_payment(identifier='PAYMENT_3', account=account2, state=PaymentState.READY_TO_PROCESS).save() with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): out = StringIO() err = StringIO() call_command('process_payments', '--exclude-accounts', '987654/3210', stdout=out, stderr=err) self.assertEqual(out.getvalue(), '') self.assertEqual(err.getvalue(), '') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 2 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_exclusion_of_non_existing_account_in_payment_processing(self): """Test excluding non-existing accounts from payment processing""" self._test_non_existing_account('--exclude-accounts') @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_inclusion_in_payment_processing(self): """Test including accounts from payment processing""" account2 = BankAccount(account_number='987654/3210', currency='CZK') account2.save() get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS).save() get_payment(identifier='PAYMENT_3', account=account2, state=PaymentState.READY_TO_PROCESS).save() with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): out = StringIO() err = StringIO() call_command('process_payments', '--include-accounts', '123456/7890', stdout=out, stderr=err) self.assertEqual(out.getvalue(), '') self.assertEqual(err.getvalue(), '') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 2 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_inclusion_of_non_existing_account_in_payment_processing(self): """Test including non-existing accounts from payment processing""" self._test_non_existing_account('--include-accounts') @override_settings( PAIN_PROCESSORS={ 'dummy': 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' }) def test_card_payments_processed(self): get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy').save() get_payment(identifier='PAYMENT_3', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy').save() with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual(BankPayment.objects.values_list( 'identifier', 'state', 'processor'), [('PAYMENT_1', PaymentState.PROCESSED, 'dummy'), ('PAYMENT_2', PaymentState.PROCESSED, 'dummy'), ('PAYMENT_3', PaymentState.PROCESSED, 'dummy')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'True objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 3 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings(PAIN_PROCESSORS=OrderedDict([ ('dummy', 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' ), ('dummy_false', 'django_pain.tests.commands.test_process_payments.DummyFalsePaymentProcessor' ), ])) def test_card_payments_unprocessed(self): get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy_false', transaction_date=date(2018, 5, 10)).save() get_payment(identifier='PAYMENT_3', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy', transaction_date=date(2018, 5, 11)).save() with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual( BankPayment.objects.values_list('identifier', 'state', 'processor'), [('PAYMENT_1', PaymentState.PROCESSED, 'dummy'), ('PAYMENT_2', PaymentState.DEFERRED, 'dummy_false'), ('PAYMENT_3', PaymentState.PROCESSED, 'dummy')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'True objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 3 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments with processor dummy_false.'), ('django_pain.management.commands.process_payments', 'INFO', 'Saving payment %s as DEFERRED with error None.' % BankPayment.objects.get(identifier='PAYMENT_2').uuid), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), ) @override_settings(PAIN_PROCESSORS=OrderedDict([ ('dummy', 'django_pain.tests.commands.test_process_payments.DummyTruePaymentProcessor' ), ('dummy_error', 'django_pain.tests.commands.test_process_payments.DummyFalseErrorPaymentProcessor' ), ])) def test_card_payments_defferred(self): get_payment(identifier='PAYMENT_2', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy_error', transaction_date=date(2018, 5, 10)).save() get_payment(identifier='PAYMENT_3', account=self.account, state=PaymentState.READY_TO_PROCESS, payment_type=PaymentType.CARD_PAYMENT, counter_account_number='', processor='dummy', transaction_date=date(2018, 5, 11)).save() with override_settings(PAIN_PROCESS_PAYMENTS_LOCK_FILE=os.path.join( self.tempdir.path, 'test.lock')): call_command('process_payments') self.assertQuerysetEqual( BankPayment.objects.values_list('identifier', 'state', 'processor'), [('PAYMENT_1', PaymentState.PROCESSED, 'dummy'), ('PAYMENT_2', PaymentState.DEFERRED, 'dummy_error'), ('PAYMENT_3', PaymentState.PROCESSED, 'dummy')], transform=tuple, ordered=False) self.assertEqual(BankPayment.objects.first().objective, 'True objective') self.log_handler.check( ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments started.'), ('django_pain.management.commands.process_payments', 'INFO', 'Lock acquired.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing 3 unprocessed payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Processing card payments with processor dummy_error.'), ('django_pain.management.commands.process_payments', 'INFO', 'Saving payment %s as DEFERRED with error PaymentProcessingError.DUPLICITY.' % BankPayment.objects.get(identifier='PAYMENT_2').uuid), ('django_pain.management.commands.process_payments', 'INFO', 'Processing payments with processor dummy.'), ('django_pain.management.commands.process_payments', 'INFO', 'Marking 0 unprocessed payments as DEFERRED.'), ('django_pain.management.commands.process_payments', 'INFO', 'Command process_payments finished.'), )