Profile - Part 2 - Unhappy Paths


In the previous video we added in the functionality to view a User's Profile.

We covered the "happy path" journey.

Of course, most of our time as developers is spent on the "unhappy paths". These may be the result of unexpected bugs, or in the case of the two extra tests we will add here, validating that if a User tries any funny business, they will receive an appropriate error message.

In certain circumstances we won't need to write any additional code to make our tests pass.

If you think about it from a purely unit testing perspective, we might have something like this:

<?php

class Calculator
{
    public function add(int num1, int num2) : int
    {
        return num1 + num2;
    }
}

class CalculatorTests extends PHPUnit_Framework_TestCase
{
    private $calc;

    protected function setUp()
    {
        $this->calc = new Calculator();
    }

    public function testadd()
    {
        $this->assertEquals(
            6,
            $this->calc->add(3,3)
        );
    }

Assuming our Calculator class isn't a complete shambles, we can safely assume that 3+3=6.

We could add in another test to prove it isn't broken:

    public function testNotAShambles()
    {
        $this->assertNotEquals(
            6,
            $this->calc->add(1,3)
        );
    }

This test should still pass, but we didn't need to write extra code.

A very contrived example, but the Behat tests operate in the same way.

Additional Behat Scenarios

Let's get onto the extra Scenarios:

# /src/AppBundle/Features/profile.feature

Feature: Manage User profile data via the RESTful API

  In order to allow a user to keep their profile information up to date
  As a client software developer
  I need to be able to let users read and update their profile

  Background:
    Given there are Users with the following details:
      | id | username | email          | password |
      | 1  | peter    | peter@test.com | testpass |
      | 2  | john     | john@test.org  | johnpass |
     And I am successfully logged in with username: "peter", and password: "testpass"
     And I set header "Content-Type" with value "application/json"

  Scenario: Cannot view a profile with a bad JWT
    When I set header "Authorization" with value "Bearer bad-token-string"
     And I send a "GET" request to "/profile/1"
    Then the response code should be 401
     And the response should contain "Invalid JWT Token"

  Scenario: Can view own profile
    When I send a "GET" request to "/profile/1"
    Then the response code should be 200
     And the response should contain json:
      """
      {
        "id": "1",
        "username": "peter",
        "email": "peter@test.com"
      }
      """

  Scenario: Cannot view another user's profile
    When I send a "GET" request to "/profile/2"
    Then the response code should be 403

I've added a Scenario in before our existing scenario, and one after.

The reason for placing these "out of order" is that - for me - this reads more like how I would expect the system to behave.

If you send in an invalid JWT, it doesn't work.

If you send in a valid JWT, and ask for the matching User, it works.

If you send in a valid JWT, and ask for a different User, it doesn't work.

You're free to change this up as you see fit, of course.

Going a little higher level here, we have added some really useful functionality here. Even though our Behat scenarios are "code", they function as human readable documentation. You could easily show a project stakeholder these files and expect some level of understanding.

Now, I admit that a number of stakeholders may not understand a 401 code, or a 403 code. I justify this (to myself) by saying that an API is a technical solution. The front end that would be used against this API would read in a manner that makes more sense to a non-technical person. Ultimately though, to each their own.

Code For This Course

Get the code for this course.

Episodes