Mastermind - set up the Python skeleton
Tags: python, programming, devops, beginners
Published: 2022-12-13 19:57:00

---
title: Mastermind - set up the Python skeleton
published: true
description: It is important to start testing early and to make sure we have Continuou Integration that will run the tests even if the authors forget it. 
tags: python, programming, devops, beginners
# cover_image: https://direct_url_to_image.jpg
# Use a ratio of 100:42 for best results.
published_at: 2022-12-13 19:57 +0000
series: mastermind
---

## Git and README

The first thing was to create a git repository, write a `README.md` file describing the game. Similar to what I posted in the first article of this series.

## Create the first test

Then create a file called `tests/test_game.py` with the following content:

```python
import mastermind.game as mm

def test_game():
    mm.play()
    assert True
```

It is not much, but I wanted to see that the tests are going to work.

I also installed pytest:

```
pip install pytest
```

Then running `pytest`:

```
pytest
```

got the following error

```
ModuleNotFoundError: No module named 'mastermind'
```

This is of course not surprising as I have not created that module.

## Creating the skeleton of the module

Next step was to create the file that will hold the implementation of the game. I created the file `mastermind/game.py` with the following content:

```python
def play():
    ...
```

Very minimalistic, I know, but enough to satisfy the test:

```
PYTHONPATH=. pytest
```

This time it was successful.

## Setting up GitHub Actions for Continuous Integration (CI)

Having tests is great. Having a CI to run them on every `push` and every `pull-request` is way better.

So I created the file `.github/workflows/ci.yml` with the following content:


```yaml
name: CI

on:
  push:
  pull_request:
  workflow_dispatch:
#  schedule:
#    - cron: '42 5 * * *'

jobs:
  test:
    strategy:
      fail-fast: false
      matrix:
        runner: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.10", "3.11"]

    runs-on: ${{matrix.runner}}
    name: OS ${{matrix.runner}} Python ${{matrix.python-version}}

    steps:
    - name: Checkout
      uses: actions/checkout@v3

    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v4
      with:
        python-version: ${{ matrix.python-version }}

    - name: Install dependencies
      run: |
        # pip install -r requirements.txt
        pip install pytest

    - name: Check Python version
      run: python -V

    - name: Test with pytest
      env:
        PYTHONPATH: .
      run: pytest -vs
```

It is funny that so far this is the most complex part of the project, but it won't change a lot.

The last file I added was the `.gitignore` file with the following content:

```
__pycache__
*.bak
```

This will help me ensure that we don't add generated files to git by mistake.

## Directory layout

To make it easier to understand the project I am also including the directory layout we have now:


```
.
├── mastermind
│   └── game.py
├── README.md
├── .gitignore
└── tests
    └── test_game.py
```

## Conclusion

OK, so when I started to write this project I thought I'll have more free time to make more progress, but after I published the introduction something came up and I only managed to get to this point. Nevertheless one have to start somewhere and it isn't that horrible to make slow progress.
I hope tomorrow I'll have some more time to work on this.