diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 984d28de2f452053ade585370a495c1be94b699e..e8d8cbb3b66ae2d7258460da29d6603ea8d2f107 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,7 +11,10 @@ debian:
   script:
     # Get various dependencies
     - apt update -y
-    - apt install -y g++ libsimgrid-dev libzmq3-dev libprotobuf-dev protobuf-compiler libgtest-dev meson ninja-build pkg-config python3 python3-pip
+    - apt install -y g++ libsimgrid-dev libzmq3-dev libprotobuf-dev protobuf-compiler libgtest-dev meson ninja-build pkg-config python3 python3-pip python3-pytest
+
+    # Put pip-installed binaries in PATH
+    - export PATH="${PATH}:/usr/local/bin"
 
     # Build protocol (c++)
     - (cd protocol && meson setup build --prefix=/usr && ninja -C build && meson install -C build)
@@ -29,10 +32,13 @@ debian:
     # Run unit tests (simgrid simulator, c++)
     - (cd simgrid-simulator && meson test -C build)
 
+    # Run unit tests (python)
+    - (cd client-py && pytest .)
+
     # Run integration tests (simgrid simulator VS c++ client)
     - test/simulator-cpp-client.sh
     # Run integration tests (simgrid simulator VS python client)
-    - PATH="${PATH}:/usr/local/bin" test/simulator-py-client.sh
+    - test/simulator-py-client.sh
   artifacts:
     paths:
       - client-cpp.err
@@ -54,5 +60,6 @@ nix:
     # Any dependency will also be built, for example the following command also builds protocol-python
     - nix-build . -A client-py
     # Therefore one can just run its desired leaf of the build tree, such as:
+    - nix-shell . -A client-py_unittest_shell --command '(cd client-py && pytest)'
     - nix-shell . -A integration_shell_cpp --command './test/simulator-cpp-client.sh'
     - nix-shell . -A integration_shell_py --command './test/simulator-py-client.sh'
diff --git a/client-py/client.py b/client-py/client.py
index 1b527b460ec2ea733c83f7f16b46d1e895171da1..1adddfa84ea4081061c3f056329dbb2a95aa555f 100755
--- a/client-py/client.py
+++ b/client-py/client.py
@@ -2,6 +2,9 @@
 import zmq
 import protocol.hello_pb2 as proto
 
+def some_function(x):
+    return x*2
+
 def main():
     context = zmq.Context()
     socket = context.socket(zmq.REP)
diff --git a/client-py/test_client.py b/client-py/test_client.py
new file mode 100644
index 0000000000000000000000000000000000000000..ba292d5bb773667914649a88b4e024d2afff41a1
--- /dev/null
+++ b/client-py/test_client.py
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+import client
+
+def test_some_function():
+    for i in range(10):
+        assert(client.some_function(i) == i*2)
diff --git a/default.nix b/default.nix
index 05eab10e079690079f395538aa835d703f4160a6..d9b4a6bb4f2beb0876b3b55905699b91f6d367fd 100644
--- a/default.nix
+++ b/default.nix
@@ -44,7 +44,11 @@ let self = rec {
       "src"
       "src/.*\.cpp"
       "src/.*\.hpp"
+      "test"
+      "test/.*\.cpp"
     ];
+    mesonFlags = [ "-Ddo_unit_tests=true" ];
+    doCheck = true;
     buildInputs = with pkgs; [
       simgrid
       protocol-cpp
@@ -85,6 +89,11 @@ let self = rec {
     ];
   };
 
+  client-py_unittest_shell = pkgs.mkShell {
+    buildInputs = client-py.propagatedBuildInputs ++ [
+      pythonPackages.pytest
+    ];
+  };
   integration_shell_cpp = pkgs.mkShell {
     buildInputs = [
       simgrid-simulator