Improving testing coverage

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.

Tip

We just created a few unit tests to understand how we can code them. However, of course, it would be necessary to write more tests to provide an appropriate coverage of all the featured and execution scenarios included in the API.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.168.8