def test_live_rollout_updates_population_percent(self): experiment = ExperimentFactory.create( type=Experiment.TYPE_ROLLOUT, status=Experiment.STATUS_LIVE, normandy_id=1234, population_percent=decimal.Decimal("25.000"), ) mock_response_data = { "approved_revision": { "enabled": True, "filter_object": [{ "type": "bucketSample", "count": 5000, "total": 10000 }], } } mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status = mock.Mock() mock_response.raise_for_status.side_effect = None mock_response.status_code = 200 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.population_percent, decimal.Decimal("50.000"))
def test_experiment_without_normandy_ids(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=None) ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=None) tasks.update_experiment_info() self.mock_normandy_requests_get.assert_not_called()
def test_experiment_with_no_recipe_data(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234 ) mock_response_data = {"approved_revision": None} mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status = mock.Mock() mock_response.raise_for_status.side_effect = None mock_response.status_code = 200 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_ACCEPTED) self.assertFalse( experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists() )
def test_update_ready_to_ship_experiment_with_pre_existing_recipe(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=2 ) mock_response_data = {"results": [{"id": 2}, {"id": 10}, {"id": 100}]} mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status = mock.Mock() mock_response.raise_for_status.side_effect = None mock_response.status_code = 200 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() experiment = Experiment.objects.get(id=experiment.id) self.assertEqual(experiment.status, Experiment.STATUS_ACCEPTED) self.assertEqual(experiment.normandy_id, 2) self.assertCountEqual(experiment.other_normandy_ids, [10, 100]) self.assertTrue( experiment.changes.filter( old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_ACCEPTED, ).exists() )
def test_accepted_experiment_becomes_live_if_normandy_enabled(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234, proposed_start_date=date.today(), proposed_duration=30, proposed_enrollment=0, ) tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertTrue( experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists()) # status is live so bugzilla should be called experiment2 = Experiment.objects.get(id=experiment.id) comment = "Start Date: {} End Date: {}".format(experiment2.start_date, experiment2.end_date) self.mock_bugzilla_requests_post.assert_called_with( settings.BUGZILLA_COMMENT_URL.format(id=experiment2.bugzilla_id), {"comment": comment}, ) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].recipients(), [experiment.owner.email])
def test_update_ready_to_ship_experiment(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_SHIP ) mock_response_data = { "results": [ {"id": 1, "latest_revision": {"creator": {"email": "*****@*****.**"}}}, {"id": 10}, {"id": 100}, ] } mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status = mock.Mock() mock_response.raise_for_status.side_effect = None mock_response.status_code = 200 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() experiment = Experiment.objects.get(id=experiment.id) self.assertEqual(experiment.status, Experiment.STATUS_ACCEPTED) self.assertEqual(experiment.normandy_id, 1) self.assertCountEqual(experiment.other_normandy_ids, [10, 100]) self.assertTrue( experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_SHIP, new_status=Experiment.STATUS_ACCEPTED, ).exists() )
def test_one_failure_does_not_affect_other_experiment_status_updates(self): self.setUpMockNormandyFailWithSpecifiedID("1234") ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234) ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1235) tasks.update_experiment_info() updated_experiment = Experiment.objects.get(normandy_id=1234) updated_experiment2 = Experiment.objects.get(normandy_id=1235) self.assertEqual(updated_experiment.status, Experiment.STATUS_ACCEPTED) self.assertEqual(updated_experiment2.status, Experiment.STATUS_LIVE) self.assertFalse( updated_experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists()) self.assertTrue( updated_experiment2.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists())
def test_experiment_with_no_creator_in_recipe(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234) mock_response_data = { "approved_revision": { "enabled": True, "enabled_states": [{ "creator": None }], } } mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status = mock.Mock() mock_response.raise_for_status.side_effect = None mock_response.status_code = 200 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertTrue( experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists())
def test_send_enrollment_pausing_email(self): exp_1 = ExperimentFactory.create( status=Experiment.STATUS_LIVE, normandy_id=1234, proposed_start_date=date.today(), proposed_enrollment=4, proposed_duration=30, ) ExperimentFactory.create( status=Experiment.STATUS_LIVE, normandy_id=1111, proposed_start_date=date.today(), proposed_enrollment=5, proposed_duration=30, ) ExperimentFactory.create( status=Experiment.STATUS_LIVE, normandy_id=1111, proposed_start_date=date.today(), proposed_enrollment=8, proposed_duration=30, ) ExperimentEmail.objects.create( experiment=exp_1, type=ExperimentConstants.EXPERIMENT_PAUSES) tasks.update_experiment_info() self.assertEqual(len(mail.outbox), 1)
def test_experiment_with_pause_val_change(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234) self.assertFalse(experiment.is_paused) tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertTrue(experiment.is_paused)
def test_update_live_experiment_not_updated(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234) tasks.update_experiment_info() self.mock_tasks_add_start_date_comment.delay.assert_not_called() self.mock_tasks_comp_experiment_update_res.delay.assert_not_called() self.mock_tasks_set_is_paused_value.delay.assert_called()
def test_live_experiment_stays_live_if_normandy_enabled(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234) tasks.update_experiment_info() updated_experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(updated_experiment.status, Experiment.STATUS_LIVE) self.assertFalse( updated_experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_LIVE, new_status=Experiment.STATUS_COMPLETE, ).exists())
def test_update_accepted_experiment_task(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234) tasks.update_experiment_info() self.mock_tasks_add_start_date_comment.delay.assert_called() self.mock_tasks_set_is_paused_value.delay.assert_called() self.mock_tasks_comp_experiment_update_res.delay.assert_not_called() self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].recipients(), [experiment.owner.email])
def test_experiment_status_updates_by_existing_user(self): User = get_user_model() user = UserFactory(email="*****@*****.**") self.assertTrue(User.objects.filter(email="*****@*****.**").exists()) ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234) tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertTrue( experiment.changes.filter( changed_by=user, old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists())
def test_experiment_with_paused_staying_the_same(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234, is_paused=False, ) self.mock_normandy_requests_get.return_value = ( self.buildMockSucessWithNoPauseEnrollment()) tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertFalse(experiment.is_paused)
def test_update_live_experiment_task(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234) self.mock_normandy_requests_get.return_value = ( self.buildMockSuccessDisabledResponse()) tasks.update_experiment_info() self.mock_tasks_comp_experiment_update_res.delay.assert_called() self.mock_tasks_set_is_paused_value.delay.assert_not_called() self.mock_tasks_add_start_date_comment.delay.assert_not_called() # No email was sent self.assertEqual(len(mail.outbox), 0)
def test_accepted_experiment_becomes_live_if_normandy_enabled(self): experiment = ExperimentFactory.create( normandy_id=1234, proposed_start_date=date.today(), proposed_duration=30, proposed_enrollment=1, ) experiment.status = Experiment.STATUS_LIVE experiment.save() tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].recipients(), [experiment.owner.email])
def test_doesnt_send_experiment_status_emails_if_only_accepted(self): ExperimentFactory.create( status=Experiment.STATUS_ACCEPTED, proposed_start_date=date.today(), proposed_duration=5, proposed_enrollment=0, ) ExperimentFactory.create( status=Experiment.STATUS_ACCEPTED, proposed_start_date=date.today(), proposed_duration=30, proposed_enrollment=5, ) tasks.update_experiment_info() self.assertEqual(len(mail.outbox), 0)
def test_experiment_with_re_enabled_enrollment(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234, is_paused=True, ) self.mock_normandy_requests_get.return_value = ( self.buildMockSucessWithNoPauseEnrollment()) tasks.update_experiment_info() experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(experiment.status, Experiment.STATUS_LIVE) self.assertFalse(experiment.is_paused) self.assertEquals(experiment.changes.latest().message, "Enrollment Re-enabled")
def test_accepted_experiment_stays_accepted_if_normandy_disabled(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_ACCEPTED, normandy_id=1234) self.mock_normandy_requests_get.return_value = ( self.buildMockSuccessDisabledResponse()) tasks.update_experiment_info() updated_experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(updated_experiment.status, Experiment.STATUS_ACCEPTED) self.assertFalse( updated_experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_ACCEPTED, new_status=Experiment.STATUS_LIVE, ).exists()) # status is still accepted so no bugzilla update self.mock_bugzilla_requests_post.assert_not_called()
def test_update_accepted_experiment_task(self): experiment = ExperimentFactory.create( status=Experiment.STATUS_ACCEPTED, normandy_id=1234, proposed_enrollment=60, proposed_duration=60, ) tasks.update_experiment_info() recipe = self.buildMockSuccessEnabledResponse().json()["approved_revision"] self.mock_tasks_add_start_date_comment.delay.assert_called_with(experiment.id) self.mock_tasks_set_is_paused_value.delay.assert_called_with( experiment.id, recipe ) self.mock_tasks_comp_experiment_update_res.delay.assert_not_called() self.assertEqual(len(mail.outbox), 1) self.assertEqual(mail.outbox[0].recipients(), [experiment.owner.email])
def test_live_experiment_becomes_complete_if_normandy_disabled(self): ExperimentFactory.create_with_status( target_status=Experiment.STATUS_LIVE, normandy_id=1234) self.mock_normandy_requests_get.return_value = ( self.buildMockSuccessDisabledResponse()) tasks.update_experiment_info() updated_experiment = Experiment.objects.get(normandy_id=1234) self.assertEqual(updated_experiment.status, Experiment.STATUS_COMPLETE) self.assertTrue( updated_experiment.changes.filter( changed_by__email="*****@*****.**", old_status=Experiment.STATUS_LIVE, new_status=Experiment.STATUS_COMPLETE, ).exists()) self.mock_bugzilla_requests_put.assert_called_with( settings.BUGZILLA_UPDATE_URL.format( id=updated_experiment.bugzilla_id), { "status": "RESOLVED", "resolution": "FIXED" }, )
def test_ship_experiment_not_updated(self): experiment = ExperimentFactory.create_with_status( target_status=Experiment.STATUS_SHIP ) mock_response_data = {} mock_response = mock.Mock() mock_response.json = mock.Mock() mock_response.json.return_value = mock_response_data mock_response.raise_for_status.side_effect = None mock_response.status_code = 404 self.mock_normandy_requests_get.return_value = mock_response tasks.update_experiment_info() self.assertEqual(experiment.status, Experiment.STATUS_SHIP) self.assertIsNone(experiment.normandy_id) self.assertIsNone(experiment.other_normandy_ids) self.assertFalse( experiment.changes.filter( old_status=Experiment.STATUS_SHIP, new_status=Experiment.STATUS_ACCEPTED, ).exists() )