Now, we will write additional unit tests to improve the testing coverage. Specifically, we will write unit tests related to the player class based views: PlayerList
and PlayerDetail
. Open the existing games/test.py
file and insert the following lines after the last line that declares imports. We need a new import
statement and we will declare the new PlayerTests
class. The code file for the sample is included in the restful_python_chapter_04_05
folder:
from games.models import Player class PlayerTests(APITestCase): def create_player(self, name, gender): url = reverse('player-list') data = {'name': name, 'gender': gender} response = self.client.post(url, data, format='json') return response def test_create_and_retrieve_player(self): """ Ensure we can create a new Player and then retrieve it """ new_player_name = 'New Player' new_player_gender = Player.MALE response = self.create_player(new_player_name, new_player_gender) self.assertEqual(response.status_code, status.HTTP_201_CREATED) self.assertEqual(Player.objects.count(), 1) self.assertEqual( Player.objects.get().name, new_player_name) def test_create_duplicated_player(self): """ Ensure we can create a new Player and we cannot create a duplicate. """ url = reverse('player-list') new_player_name = 'New Female Player' new_player_gender = Player.FEMALE response1 = self.create_player(new_player_name, new_player_gender) self.assertEqual( response1.status_code, status.HTTP_201_CREATED) response2 = self.create_player(new_player_name, new_player_gender) self.assertEqual( response2.status_code, status.HTTP_400_BAD_REQUEST) def test_retrieve_players_list(self): """ Ensure we can retrieve a player """ new_player_name = 'New Female Player' new_player_gender = Player.FEMALE self.create_player(new_player_name, new_player_gender) url = reverse('player-list') response = self.client.get(url, format='json') self.assertEqual( response.status_code, status.HTTP_200_OK) self.assertEqual( response.data['count'], 1) self.assertEqual( response.data['results'][0]['name'], new_player_name) self.assertEqual( response.data['results'][0]['gender'], new_player_gender)
The PlayerTests
class is a subclass of rest_framework.test.APITestCase
. The class declares the create_player
method that receives the desired name
and gender
for the new player as arguments. The method builds the url and the data dictionary to compose and send an HTTP POST
method to the view associated with the player-list
view name and returns the response generated by this request. Many test methods will call the create_player
method to create a player and then compose and send other HTTP requests to the API.
The class declares the following methods that start whose name start with the test_
prefix:
test_create_and_retrieve_player
: Tests whether we can create a new Player
and then retrieve it.test_create_duplicated_player
: Tests whether the unique constraints don't make it possible for us to create two players with the same name. The second time we compose and send an HTTP POST request with a duplicate player name, we must receive an HTTP 400 Bad Request status code (status.HTTP_400_BAD_REQUEST
).test_retrieve_player_list
: Tests whether we can retrieve a specific game category by its primary key or id.We just coded a few tests related to players to improve test coverage and notice the impact on the test coverage report.
Now, run the following command within the same virtual environment we have been using. We will use the -v 2
option to use the verbosity level 2 because we want to check all the things that the test runner is doing:
python manage.py test -v 2
The following lines show the last lines of the sample output:
Ensure we can create a new GameCategory and then retrieve it ... ok Ensure we can create a new GameCategory. ... ok Ensure we can filter a game category by name ... ok Ensure we can retrieve a game cagory ... ok Ensure we can update a single field for a game category ... ok Ensure we can create a new Player and then retrieve it ... ok Ensure we can create a new Player and we cannot create a duplicate. ... ok Ensure we can retrieve a player ... ok Name Stmts Miss Cover ------------------------------------------ games.py 0 0 100% games/admin.py 1 1 0% games/apps.py 3 3 0% games/models.py 36 34 6% games/pagination.py 3 0 100% games/permissions.py 6 3 50% games/serializers.py 45 0 100% games/urls.py 3 0 100% games/views.py 91 2 98% ------------------------------------------ TOTAL 188 43 77% ---------------------------------------------------------------------- Ran 8 tests in 0.168s OK Destroying test database for alias 'default' ('test_games')...
The output provides details that indicate that the test runner executed 8 tests and all of them passed. The test code coverage measurement report provided by the coverage
package increased the Cover
percentage from 3% in the previous run to 6%. The additional tests we wrote execute code for the Player
model, and therefore, there is an impact in the coverage report.
18.191.168.8