Repository: spotify/luigi
File: test/interface_test.py (Python)

Code before:
        test_dict['ever_failed'].update([self.task_a])
        # Nothing in failed tasks (only an entry in ever_failed) so, should succeed with retry
        fake_summary_dict.return_value = test_dict
        self.worker.run = Mock(return_value=False)
        ret = self._run_interface(detailed_summary=True)

        self.assertEqual(ret.status, LuigiStatusCode.SUCCESS_WITH_RETRY)
        self.assertEqual(ret.scheduling_succeeded, False)
        self.assertEqual(ret.execution_succeeded, True)

    @patch(_summary_dict_module_path())
    def test_ret_code_2(self, fake_summary_dict):
        test_dict = self._empty_summary_dict()
        test_dict['ever_failed'].update([self.task_a])
        test_dict['failed'].update([self.task_a])
        # Should fail because a task failed
        fake_summary_dict.return_value = test_dict
        self.worker.run = Mock(return_value=False)
        ret = self._run_interface(detailed_summary=True)

        self.assertEqual(ret.status, LuigiStatusCode.FAILED)
        self.assertEqual(ret.scheduling_succeeded, False)
        self.assertEqual(ret.execution_succeeded, False)

    @patch(_summary_dict_module_path())
    def test_ret_code_3(self, fake_summary_dict):
        test_dict = self._empty_summary_dict()
        test_dict['ever_failed'].update([self.task_a])
        test_dict['failed'].update([self.task_a])
        test_dict['scheduling_error'].update([self.task_b])
        # Failed task and also a scheduling error
        fake_summary_dict.return_value = test_dict
        self.worker.add = Mock(side_effect=[True, False])
        self.worker.run = Mock(return_value=False)
        ret = self._run_interface(detailed_summary=True)

        self.assertEqual(ret.status, LuigiStatusCode.FAILED_AND_SCHEDULING_FAILED)
        self.assertEqual(ret.scheduling_succeeded, False)
        self.assertEqual(ret.execution_succeeded, False)

    @patch(_summary_dict_module_path())
    def test_ret_code_4(self, fake_summary_dict):
        test_dict = self._empty_summary_dict()
        test_dict['scheduling_error'].update([self.task_b])
        # Scheduling error for at least one task
        fake_summary_dict.return_value = test_dict
        self.worker.add = Mock(side_effect=[True, False])
        self.worker.run = Mock(return_value=True)
        ret = self._run_interface(detailed_summary=True)

        self.assertEqual(ret.status, LuigiStatusCode.SCHEDULING_FAILED)

Review comment (bug):
Don't call the test cases `_1`, `_2`, `_3` etc. How can we remember what they are testing?

Instead call them like `test_the_status_is_failed_and_scheduling_failed_case`, or in other cases it could be `test_that_status_is_failed_when_there_is_one_failed_task`.

Code after:
        # Nothing in failed tasks (only an entry in ever_failed) so, should succeed with retry
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'ever_failed': [self.task_a]
        })
        luigi_run_result = self._run_interface(detailed_summary=True)
        self.assertEqual(luigi_run_result.status, LuigiStatusCode.SUCCESS_WITH_RETRY)

    @patch(_summary_dict_module_path())
    def test_that_status_is_failed_when_there_is_one_failed_task(self, fake_summary_dict):
        # Should fail because a task failed
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'ever_failed': [self.task_a],
            'failed': [self.task_a]
        })
        luigi_run_result = self._run_interface(detailed_summary=True)
        self.assertEqual(luigi_run_result.status, LuigiStatusCode.FAILED)

    @patch(_summary_dict_module_path())
    def test_that_status_is_failed_with_scheduling_failure(self, fake_summary_dict):
        # Failed task and also a scheduling error
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'ever_failed': [self.task_a],
            'failed': [self.task_a],
            'scheduling_error': [self.task_b]
        })
        luigi_run_result = self._run_interface(detailed_summary=True)
        self.assertEqual(luigi_run_result.status, LuigiStatusCode.FAILED_AND_SCHEDULING_FAILED)

    @patch(_summary_dict_module_path())
    def test_that_status_is_scheduling_failed_with_one_scheduling_error(self, fake_summary_dict):
        # Scheduling error for at least one task
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'scheduling_error': [self.task_b]
        })
        luigi_run_result = self._run_interface(detailed_summary=True)
        self.assertEqual(luigi_run_result.status, LuigiStatusCode.SCHEDULING_FAILED)

    @patch(_summary_dict_module_path())
    def test_that_status_is_not_run_with_one_task_not_run(self, fake_summary_dict):
        # At least one of the tasks was not run
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'not_run': [self.task_a]
        })
        luigi_run_result = self._run_interface(detailed_summary=True)
        self.assertEqual(luigi_run_result.status, LuigiStatusCode.NOT_RUN)

    @patch(_summary_dict_module_path())
    def test_that_status_is_missing_ext_with_one_task_with_missing_external_dependency(self, fake_summary_dict):
        # Missing external dependency for at least one task
        fake_summary_dict.return_value = self._create_summary_dict_with({
            'still_pending_ext': [self.task_a]