Beispiel #1
0
    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"))
Beispiel #2
0
 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()
Beispiel #3
0
    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()
        )
Beispiel #4
0
    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()
        )
Beispiel #5
0
    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])
Beispiel #6
0
    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()
        )
Beispiel #7
0
    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())
Beispiel #8
0
    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())
Beispiel #9
0
    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)
Beispiel #10
0
    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)
Beispiel #11
0
    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()
Beispiel #12
0
 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())
Beispiel #13
0
    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])
Beispiel #14
0
 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())
Beispiel #15
0
    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)
Beispiel #16
0
    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)
Beispiel #17
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])
Beispiel #18
0
    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)
Beispiel #19
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")
Beispiel #20
0
    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()
Beispiel #21
0
    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])
Beispiel #22
0
    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"
            },
        )
Beispiel #23
0
    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()
        )