Unit Testing and validation, good sir.

Skip to content

This doth be a machine-wrought text which may contain errors!

Now that we have wrought classes and laboured with validation, we have a good foundation to begin with testing. Testing is a most vital part of the development process, and doth aid us in ensuring that our code functioneth as expected.

For how may we be certain that the code doth function as it should, if we test it not?

What is Unit Testing?

Unit Testing is a method for automatically and systematically testing small parts of our code. In Python, we employ a module hight pytest to write and run tests. A “unit” is the smallest testable part of an application, oft a single function or method. When we use pytest, ‘tis important that we follow the proper naming conventions for pytest to be able to find our tests, such as naming test files with test_ afore, and test functions with test_ afore.

Example of a unit test:

def test_add():
    assert 0.3 + 0.3 + 0.3 == 0.9 # Forsooth, this doth test the addition of floats.

Runneth by writing pytest within the terminal’s bounds.

Fun fact

Verily, the code aloft shall fail, for .3+.3+.3 doth become 0.8999999999 in the tongue of Python!

Easy Task 1 - Install pytest

Install pytest within thy virtual environment. This dost thou achieve by executing the following command in the terminal:

pip install pytest
# Installerer pytest for å kjøre tester.
# Doth install pytest, that tests may be run.

Easy Task the Second - Construct a Trial

Create a new file within thy project’s fold, and name it test_data.py. Within this file, thou shalt fashion a trial for the Person class which thou didst create in the module past. This trial shall verify that a Person may be brought forth with values lawful and true.

An example of how this trial might appear:

from main import Person

def test_person_working():
    bob_kaare = Person(name="Bob Kåre",
                       eye_color=EyeColor.BLUE,
                       phone_number=PhoneNumber("12345678"),
                       email=Email("bob_kaare@example.com"))
    assert bob_kaare.name == "Bob Kåre" # Verily, 'tis to confirm the name doth match.
    assert bob_kaare.eye_color == EyeColor.BLUE # Lo, we check the hue of his orbs.

This sort of assay is hight “happy path” testing, forasmuch as we do assay that all doth function as ‘twould when valid values we do proffer, and is not overmuch profitable.

Medium Task the Third - Assay of Validation

Compose further assays within test_person.py which do examine that the validation within Email and PhoneNumber doth function as ‘tis meant to. Assay both valid and invalid values. Here must thou employ a function in pytest hight raises, which doth check that a certain error is cast forth.

import pytest

def test_exception():
    with pytest.raises(KeyError):
        my_dict = {"a": 1, "b": 2}
        value = my_dict["c"]  # 'Tis here a KeyError shall be raised, forsooth.

Tip

Thou mayest forge as many functions as doth please thee, so long as the function’s name doth commence with test_.

Løsning: Eksempel på en test for ugyldig e-post
from main import Email

import pytest

def test_invalid_email():
    with pytest.raises(ValueError):
        email = Email("not-an-email")

Wherefore Do This?

By possessing good tests for our code, we may be assured that it doth function as ‘tis meant to, and we may with ease discern if aught hath gone awry should we make changes to the code. This is most especially vital in larger projects, where many developers labour together, and ‘tis easy to commit errors.

By employing, for example, software such as Jest or Selenium, one may test web pages automatically, and thereby ensure that all doth function as ‘tis meant to after each change to the code. We would fain know that “user registration”, “payment”, and “login” function as they should, would we not?

Prithee, ponder these scenarios

What doth befall (or should befall) if..:

  • A user doth attempt to register with an email already in use?
  • A user hath a birthdate in the future?
  • A user who doth enter the name “jOHN dOE”?

A software tester walks into a bar...

Hard Task 4 - Automatic Testing (CI)

When we do publish code upon GitHub, ‘tis possible to set up that which is called GitHub Actions, which may run our tests automatically each time we make a change in the code. This is called Continuous Integration (CI), and it doth aid us in ensuring that our code doth ever function as ‘tis meant to.

Create a file within thy project folder, named .github/workflows/pytest.yml. Within this file, thou shalt add the following code:

name: Pytest

on: [push]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v4
    - name: Set up Python
      uses: actions/setup-python@v5
      with:
        python-version: '3.11'
    - name: Install dependencies
      run: |

        python -m pip install --upgrade pip
        pip install pytest
        # Install any other dependencies your project needs
        # Installér eventuelle andre avhengigheter prosjektet ditt trenger
        pip install -r requirements.txt
    - name: Run tests with pytest
      run: pytest

If thou hast set it up aright, thou shalt now behold a new tab within thy GitHub repository, hight “Actions”. Here shalt thou be able to see that thy tests are run automatically each time thou makest a change in the code, and thou shalt be notified should any of the tests fail (a red cross and by way of post).

Merknad om filstruktur

The very frame of thy files shall determine if GitHub Actions doth flourish or no. See to it that the .github folder doth reside within the root of thy project, and so too a tests folder wherein thy test files do lie.

Thou mayest, perchance, amend the pytest.yml file to point unto the proper folder.

Such Actions files may eke be employed to assay thy code upon divers versions of Python or operating systems, they may also be used to build and publish thy software automatically, forsooth, publish a web-page, or update an app in the App Store or Google Play.

Code Coverage

There doth exist a thing yclept “Code Coverage”, which may aid thee in discerning how much of thy code is, in sooth, being tested. This may prove most helpful in determining if thou hast tests aplenty, or if there be portions of thy code which remain untried altogether.

Certain places of work do require that thou possess a certain percentage of thy code covered by tests ere thou mayest deploy it, to ensure that the code is robust and doth function as it ought.

Unit Test Meme