diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index dd2c4d85681cc6b9d7d1c8ec82ba4bcdfa3e9eae..628cd53a57e45649d501a710adcf6e84b35cc7f2 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,6 +1,7 @@
 default_language_version:
   python: python3.7
 
+exclude: snapshots/
 repos:
   - repo: https://github.com/pre-commit/pre-commit-hooks
     rev: v2.5.0
diff --git a/Makefile b/Makefile
index 3cf90142bcd4335fbd74438d37ecd3309b5482d7..09dbd69eb341062719b54d4c796f991c835cc73e 100644
--- a/Makefile
+++ b/Makefile
@@ -19,13 +19,17 @@ help:
 	@echo "  migrations     Generate migrations"
 	@echo "  migrate        Run migrations"
 	@echo ""
+	@echo "Testing:"
+	@echo "  test           Run tests"
+	@echo "  coverage       Coverage report"
+	@echo ""
 
 venv: .venv/bin/python
 .venv/bin/python:
 	${PYTHON} -m venv ${VENV}
 
 install: venv
-	${VENV}/bin/pip install -r requirements/base.txt
+	${VENV}/bin/pip install -r requirements/base.txt -r requirements/dev.txt
 
 install-hooks:
 	pre-commit install --install-hooks
@@ -45,7 +49,13 @@ migrations: venv
 migrate: venv
 	${VENV}/bin/python manage.py migrate
 
+test:
+	${VENV}/bin/pytest
+
+coverage:
+	${VENV}/bin/pytest --cov --cov-report term-missing
+
 .PHONY: help venv install install-hooks hooks run shell
-.PHONY: migrations migrate
+.PHONY: migrations migrate test coverage
 
 # EOF
diff --git a/README.md b/README.md
index f7e04655b4fef3e3fa0623c39c8bc4fcf99ba9f3..9322a7fc317779fd6e5cd8b7f72169a086590b52 100644
--- a/README.md
+++ b/README.md
@@ -153,6 +153,20 @@ Django shell používající `shell_plus` z Django extensions spustíte:
 
     $ make shell
 
+### Testy
+
+Používá se testovací framework [pytest](https://pytest.org). Spuštění testů:
+
+    $ pytest
+
+Případně přes `make`, ale bez možnosti parametrizovat spuštění testů:
+
+    $ make test
+
+Coverage report:
+
+    $ make coverage
+
 ### Code quality
 
 K formátování kódu se používá [black](https://github.com/psf/black). Doporučujeme
@@ -187,5 +201,6 @@ K upgrade se používají [pip-tools](https://github.com/jazzband/pip-tools) (`p
     $ cd requirements/
     $ pip-compile -U base.in
     $ pip-compile -U production.in
+    $ pip-compile -U dev.in
 
-Tím se vygenerují `base.txt` a `production.txt`.
+Tím se vygenerují `base.txt`, `production.txt` a `dev.txt`.
diff --git a/pytest.ini b/pytest.ini
new file mode 100644
index 0000000000000000000000000000000000000000..c9a5798015bb1749a83088367188779e861ab9ab
--- /dev/null
+++ b/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+addopts = --ds=majak.settings.dev
+python_files = test_*.py
diff --git a/requirements/dev.in b/requirements/dev.in
new file mode 100644
index 0000000000000000000000000000000000000000..bcccdaa4bd9ff4f4411120ff969a1c5ac9769a7d
--- /dev/null
+++ b/requirements/dev.in
@@ -0,0 +1,7 @@
+pytest
+pytest-sugar
+pytest-factoryboy
+pytest-cov
+pytest-django
+pytest-freezegun
+snapshottest
diff --git a/requirements/dev.txt b/requirements/dev.txt
new file mode 100644
index 0000000000000000000000000000000000000000..1bc61d2562e2ed08efea1ccd3683ab98f5983ae2
--- /dev/null
+++ b/requirements/dev.txt
@@ -0,0 +1,31 @@
+#
+# This file is autogenerated by pip-compile
+# To update, run:
+#
+#    pip-compile dev.in
+#
+attrs==19.3.0             # via pytest
+coverage==5.1             # via pytest-cov
+factory-boy==2.12.0       # via pytest-factoryboy
+faker==4.1.0              # via factory-boy
+fastdiff==0.2.0           # via snapshottest
+freezegun==0.3.15         # via pytest-freezegun
+inflection==0.4.0         # via pytest-factoryboy
+more-itertools==8.3.0     # via pytest
+packaging==20.4           # via pytest, pytest-sugar
+pluggy==0.13.1            # via pytest
+py==1.8.1                 # via pytest
+pyparsing==2.4.7          # via packaging
+pytest-cov==2.8.1         # via -r dev.in
+pytest-django==3.9.0      # via -r dev.in
+pytest-factoryboy==2.0.3  # via -r dev.in
+pytest-freezegun==0.4.1   # via -r dev.in
+pytest-sugar==0.9.3       # via -r dev.in
+pytest==5.4.2             # via -r dev.in, pytest-cov, pytest-django, pytest-factoryboy, pytest-freezegun, pytest-sugar
+python-dateutil==2.8.1    # via faker, freezegun
+six==1.14.0               # via freezegun, packaging, python-dateutil, snapshottest
+snapshottest==0.5.1       # via -r dev.in
+termcolor==1.1.0          # via pytest-sugar, snapshottest
+text-unidecode==1.3       # via faker
+wasmer==0.4.1             # via fastdiff
+wcwidth==0.1.9            # via pytest