Testing Python projects with Tox

Hi 👋

In this article I will show you how to test your Python projects with Tox.

Introduction

Tox is a tool for automating testing in Python, their vision is to standardize the testing process. It can be used to easily test your project using multiple Python interpreters and run various commands.

Getting Started

To get started all you need to add to your project is a tox.ini file. To simplify running the tests we will make use of the following Dockerfile, which contains Python interpreters for 3.6 and 3.7

FROM ubuntu:20.04

RUN apt update && apt install -y software-properties-common \
               && add-apt-repository ppa:deadsnakes/ppa \
               && apt install -y python3.6 && apt install -y python3.7 \
               && apt install -y python3-pip && pip3 install tox

VOLUME /code

WORKDIR /code
ENTRYPOINT tox

A tox.ini file which tests using python 3.6 and python 3.7 looks like this:

# content of: tox.ini , put in same dir as setup.py
[tox]
skip_missing_interpreters = True
envlist = py36,py37

[testenv]
# install pytest in the virtualenv where commands will be executed
deps =
    pytest==6.2.1
    pytest-cov==2.11.1
    responses==0.13.3
commands =
    # NOTE: you can run any command line tool here – not just tests
    pytest

[testenv:bamboo]
commands =
  pytest —junitxml=results.xml \
    —cov=your-module—cov-config=tox.ini —cov-report=xml
    coverage2clover -i coverage.xml -o clover.xml
deps =
    {[testenv]deps}
    coverage2clover

We have two environments: testenv and testenv:bamboo, the later one being used for coverage reporting in Bamboo using clover. To run Tox with a specific environment you’d type tox -e bamboo.

To run the test via the Dockerfile, first you’d build the docker container using: docker build . -f Dockerfile -t tox

Then, you’d run the container with docker run -v “$(pwd)”:”/code” tox -e bamboo to test with the Bamboo environment or just docker run -v “$(pwd)”:”/code” tox for the default env.

Practical Example

Here’s an example that you can use to follow along. We have the following files:

@denis ➜ tox_article ls
__pycache__  tests.py  tox.ini
# @denis ➜ tox_article cat tests.py
import unittest

class TestStringMethods(unittest.TestCase):

    def test_upper(self):
        self.assertEqual('foo'.upper(), 'FOO')

    def test_isupper(self):
        self.assertTrue('FOO'.isupper())
        self.assertFalse('Foo'.isupper())

    def test_split(self):
        s = 'hello world'
        self.assertEqual(s.split(), ['hello', 'world'])
        # check that s.split fails when the separator is not a string
        with self.assertRaises(TypeError):
            s.split(2)

if __name__ == '__main__':
    unittest.main()%
# @denis ➜ tox_article cat tox.ini
[tox]
skip_missing_interpreters = True
envlist = py36,py37
skipsdist = True

[testenv]
commands =
    python -m unittest%

Running Tox in our docker image will yield the following output:

@denis ➜ tox_article docker run -v "$(pwd)":"/code" tox
py36 create: /code/.tox/py36
py36 run-test-pre: PYTHONHASHSEED='520882151'
py36 run-test: commands[0] | python -m unittest
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
py37 create: /code/.tox/py37
py37 run-test-pre: PYTHONHASHSEED='520882151'
py37 run-test: commands[0] | python -m unittest
...
----------------------------------------------------------------------
Ran 3 tests in 0.000s

OK
___________________________________ summary ____________________________________
  py36: commands succeeded
  py37: commands succeeded
  congratulations 🙂

The same tests are run twice, first with Python 3.6 and then with Python 3.7.

Thanks for reading and happy testing! 🔧

Docker basics for Developers

Introduction

Hello 🙋‍♂️

In this article we will discuss a tool called Docker 🐬

Docker is a platform which allows to package individual applications in containers. This achieves application isolation at the OS level without the need to use virtualization technologies by making use of the OS APIs.

Since it can be a little hard to get into Docker if you are new I will try to keep things short and concise.

A little example

Let us say you want to deploy two Applications on a Linux box, and one of them depends on imagemagick library version A and the other one depends on version B.

Since you can have only one version of the library installed at the same time you cannot deploy both applications. ☹

With Docker, you can package the Application and all its dependencies into containers. 📦

Something you can probably achieve without Docker as well if you try hard enough. But Docker makes this amazingly easy for us.

Once you’ve packaged your application you can publish it on  the Docker Hub so other people can make use of.

Let us recap:

  • 🐬Docker is a platform that empowers developers.
  • ☁Docker Hub is a Hub for sharing Docker containers, tools and plugins.
  • 📦Container is an abstraction at the application level.

Installing Docker ⚙

To install Docker, follow the official guide it is well written.

If you are on Windows 10 Home, I recommend you install WSL and WSL2 before installing Docker.

Install WSL on Windows 10 | Microsoft Docs

Packaging 📦

To package you will need a Dockerfile. The Dockerfile is a text document that contains all the steps needed to package the application into a container.

For a Golang application an example Dockerfile would look like this:

# Golang is our base images.
FROM golang:1.7

# Make a directory called simplFT
RUN mkdir -p /go/src/github.com/metonimie/simplFT/

# Copy the current dir contents into simplFT
ADD . /go/src/github.com/metonimie/simplFT/

# Set the working directory to simplFT
WORKDIR /go/src/github.com/metonimie/simplFT/

# Install dependencies
RUN go get "github.com/zyxar/image2ascii/ascii"
RUN go get "github.com/spf13/viper"

# Build the application
RUN go build ./main.go

# Run simplFT when the container launches
CMD ["./main", "-config-name", "docker-config"]

After you have a Dockerfile setup, you can build an image running: docker build . -f path_to_dockerfile -t my_app

Once the image is built you can use the image as a base for containers, and you can run as many as you would like: docker run -d  -p 8080:8080 -p 8081:8081 my_app

To see running containers you can write: docker ps

And to stop a container: docker stop container_id

You can also SSH into containers, mount volumes, expose ports, obtain logs and many more.

If you have secrets in the current directory!!!

Create a file called .dockerignore and include all files that contain sensitive information in it. If you do not, you may leak sensitive information into your Docker images.

Docker and Docker-Compose

Docker-compose is another tool which allows run recipes that involve multiple containers with ease.

If you are a Developer then your application will depend on other services like Nginx, Reddit, MongoDB, RabbitMQ and so on. Having to setup your DEV environment and install all these on your machine is painful a boring, and if you install the wrong version of MongoDB your application may crash.

Just like with Dockerfile you can create a docker-compose.yaml file, in which can reference third party images or your own Dockerfile.

A local development environment for WordPress would look like this:

version: "3.9"
    
services:
  db:
    image: mysql:5.7
    volumes:
      - db_data:/var/lib/mysql
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: somewordpress
      MYSQL_DATABASE: wordpress
      MYSQL_USER: wordpress
      MYSQL_PASSWORD: wordpress
    
  wordpress:
    depends_on:
      - db
    image: wordpress:latest
    volumes:
      - wordpress_data:/var/www/html
    ports:
      - "8000:80"
    restart: always
    environment:
      WORDPRESS_DB_HOST: db:3306
      WORDPRESS_DB_USER: wordpress
      WORDPRESS_DB_PASSWORD: wordpress
      WORDPRESS_DB_NAME: wordpress
volumes:
  db_data: {}
  wordpress_data: {}

You can run docker-compose up -d to start all services and docker-compose down to stop them.

The full example can be found at Quickstart: Compose and WordPress | Docker Documentation.

Thanks for reading! 🧾

Stay healthy and take care!

Adding PostgreSQL support to your ASP.Net Core application via Docker

I’ve been playing recently with ASP.Net Core and I’m developing a small Web API project in order to teach myself the framework.

In still article I’ll explain how to use a Postgres database with Docker, in order to make your development experience much more enjoyable.

Before moving on, please make sure that you’ve installed:

First, create the docker-compose.yml file in your root directory of the project, the file should contain:


version: '3.4'
services:
  postgres:
    image: postgres
    environment:
      - POSTGRES_USER=app
      - POSTGRES_PASSWORD=app
      - POSTGRES_DB=mydbname
    volumes:
      - ./volumes/data/db:/var/lib/postgresql/data
    ports:
       - 5432:5432

This specific postgres configuration passes some self-explanatory environments variables to the postgres database, it binds the ./volumes/data directory to the postgres’ data volume and it exposes the port 5432. We bind the volume so we can achieve data persistency and explore the files generated by the postgres database.

Next, add the following packages to your ASP.Net Core application:

  dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
  dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL.Design

Add your database connection configuration to the appsettings.Development.json file, note that they match the strings from the docker-compose.yml file. When running in production you should deploy each service in a separate container and configure them with environment variables. Never hardcode sensitive information in your files!

{
"DatabaseConfig": {
    "PostgresSQL": "Server=localhost;Port=5432;Database=mydbname;User Id=app;Password=app;"
  },
...
}

Now in the Startup.cs file, when configuring the application context, specify that you want to use PostgresSQL.

services.AddDbContext<ApplicationContext>(options =>
{
    options.UseNpgsql(Configuration.GetSection("DatabaseConfig")["PostgresSQL"]);
});

This is it! Make sure that your application is not running and start the database with docker-compose up. After the database has started open a new terminal and add the migrations:

dotnet ef migrations add InitialMigration
dotnet ef database update

If you’d like to stop the database you can run docker ps and docker stop <hash> where <hash> is the hash of your database container. Following the steps from above gives you an isolated development database that you can use alongside your ASP.Net Core application, if you need to add ElasticSearch, Redis or another service all you need to do is change the docker-compose.yml file to include them and voilà.

Thank you for reading, have a nice day!

Getting started with PL/SQL

I signed up for the Database Design course at my university, the courses are great but the practical laboratories are not, it’s just a bunch of tiresome SQL queries and incomplete instructions. If you too have to do a lot of tiresome SQL queries I suggest the following setup:

  1. Download Docker.
  2. Download any Intellij IDE (if you’re a student you can get it for free). Preferably DataGrip.

After you installed the aforementioned tools you start with a some docker commands:

Instructions here, if you want to explore on your own.

docker pull wnameless/oracle-xe-11g
docker run -d -p 49161:1521 wnameless/oracle-xe-11g

Now, open DataGrip, add a new data source, select Oracle and use the following settings:

hostname: localhost
port: 49161
sid: xe
username: system
password: oracle

Do not bother with the official docker images from Oracle, they usually don’t work.

Thank you for reading!