Testing always help us to figure out the unintentional bug we have committed while writing our code.
So, let’s write some tests for the gamification app we have created earlier and find out what we have missed.
We could start by testing the models and see if all the methods we designed for the Participant model is working the way we wanted:
So, let’s first setUp the required tests data:
class ParticipantModelTest(TestCase): @classmethod def setUpTestData(cls): # Set up non-modified objects used by all methods Level.objects.create(number=1, min_score=0, max_score=5, name='newbie') Level.objects.create(number=2, min_score=5, max_score=10, name='beginner') BadgeActivity.objects.create( name='Created a newcomer bug') Badge.objects.create( number=1, name='The Bug Finder') Activity.objects.create(name='Created a newcomer bug', points=5) Participant.objects.create(username='sks444') Participant.objects.create(username='test')
Now the first method we have in the participant model is
__str__ method, it means that the function object name should be the participant username:
def test_object_name_is_participant_username(self): participant = Participant.objects.get(username='sks444') expected_object_name = 'sks444' self.assertEquals(expected_object_name, str(participant))
And it passes!
The second method is class Meta ordering with
[-score], it means that the participant with the higher score would be up in the leaderboard.
def test_class_meta_ordering(self): participant1 = Participant.objects.get(username='sks444') participant1.score = 5 participant1.save() participant2 = Participant.objects.get(username='test') participant2.score = 10 participant2.save() participants = Participant.objects.all() self.assertEquals(participants.username, 'test') self.assertEquals(participants.username, 'sks444')
And it passes! As we can see that the participant
testis the first item in the list instead of
sks444because it has the highest score.
The third method is add_points which simply calls the
update_score_and_level method and
add_activity method. And the
update_score_and_level method uses the
find_level_for_score method, So let’s first test the
find_level_for_score method, which should return a level object based on the total score of the participant.
def test_find_level_for_score_method(self): participant = Participant.objects.get(username='sks444') level = participant.find_level_for_score(5) self.assertEquals(level.name, 'beginner')
And it passes!
Now, test for
update_score_and_level method, which should update the total score and level of the participant based on the activity performed and the points assigned to that activity.
def test_update_score_and_level_method(self): participant = Participant.objects.get(username='sks444') # Before update self.assertEquals(participant.score, 0) self.assertEquals(participant.level.name, 'newbie') # Update participant.update_score_and_level(5) # After update self.assertEquals(participant.score, 5) self.assertEquals(participant.level.name, 'beginner')
And it passes!
Now, the tests for the
add_activity method, which should add a new activity to the participant who performs that activity and if that activity is already performed by the participant it should increase the
number_of_times field with one.
But, wait! I just realized that our old
add_activitymethod doesn’t check if an activity is already performed by the
same is user, it just checks if an activity is performed(by any user), if yes it increases the
number_of_timesfield with one. And that has to fixed before writing the tests.
Now, let’s do some detailed testing for the modified add_activity method.
def test_add_activity_method(self): participant = Participant.objects.get(username='sks444') # Befor applying add_activity self.assertEquals(participant.activities.count(), 0) # Apply add_activity points = 5 activity = 'Created a newcomer bug' participant.add_activity(points, activity) # After applying add_activity self.assertEquals(participant.activities.count(), 1) # Performing the same activity again participant.add_activity(points, activity) # No new activity added self.assertEquals(participant.activities.count(), 1) # Number of times this activity has been performed # by the participant same_activity = participant.activities.get( name=activity, performer=participant.username) # 'number_of_times' of old activity increased by one self.assertEquals(same_activity.number_of_times, 2)
As you can see, I have done testing for all the aspects of
add_activitymethod. and it passes too:)
Similarly, I have written tests for the
add_badge, tests for other models, tests for views and the management commands too, which can be found in the gamification pr.
Phase-3 will be about improving the gamification app and improving the gitter messages analysis along with writing documentation and more testing.