diff --git a/.gitignore b/.gitignore
index 3aeb7b4cfdd3c03331af284813bfa9ac1dd5ad91..e4510e26f8a8144c334a2482ce947d5619da9ec5 100755
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,6 @@ classes/
 *.iml
 /.idea/
 .vscode/settings.json
+selenium/.pytest_cache
+selenium/.venv
+selenium/tests/__pycache__
diff --git a/selenium/Makefile b/selenium/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..46afaa456cb69f572e7293005dff92ea7cc03bff
--- /dev/null
+++ b/selenium/Makefile
@@ -0,0 +1,12 @@
+venv: venv/touchfile
+
+venv/touchfile: requirements.txt
+	python3 -m venv .venv
+	. .venv/bin/activate; python3 -m pip install --upgrade -q pip; pip install -Ur requirements.txt
+	touch .venv/touchfile
+
+test: venv 
+	@echo 'Running Django application locally'
+	. .venv/bin/activate \
+	&& pytest
+
diff --git a/selenium/README.md b/selenium/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4e050c2458fa07ed38b1dd399ec10b1cb449901a
--- /dev/null
+++ b/selenium/README.md
@@ -0,0 +1,7 @@
+# Selenium tests
+
+Ensure application is running locally. Tests expect login form to be available on http://localhost/index.html. Run tests like this:
+
+```
+$ make test
+```
diff --git a/selenium/requirements.txt b/selenium/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..4b18905fbc889d7ed4c301541ec06b763ed0911d
--- /dev/null
+++ b/selenium/requirements.txt
@@ -0,0 +1,5 @@
+selenium==4.16.0
+pytest
+trio
+pytest-trio
+flake8
\ No newline at end of file
diff --git a/selenium/tests/test_selenium.py b/selenium/tests/test_selenium.py
new file mode 100644
index 0000000000000000000000000000000000000000..b589dc783fbb83896df839f98e6bf92e385ee329
--- /dev/null
+++ b/selenium/tests/test_selenium.py
@@ -0,0 +1,74 @@
+from selenium import webdriver
+import pytest
+from selenium.webdriver.common.by import By
+from selenium.webdriver.support.ui import WebDriverWait
+from selenium.webdriver.support import expected_conditions as EC
+
+# https://github.com/SeleniumHQ/seleniumhq.github.io/blob/trunk/examples/python/README.md
+
+
+@pytest.fixture
+def browser():
+    chrome_options = webdriver.ChromeOptions()
+    chrome_options.add_argument("--headless")
+    driver = webdriver.Chrome(options=chrome_options)
+
+    driver.get("http://localhost/index.html")
+    assert driver.title == "Please log in"
+    driver.implicitly_wait(0.5)
+    driver.find_element(by=By.NAME, value="username").send_keys("seleniumtest")
+    driver.find_element(by=By.NAME, value="password").send_keys("seleniumTEST")
+    driver.find_element(by=By.CSS_SELECTOR, value="button").click()
+    assert driver.title == "Welcome to VIPSLogic"
+    yield driver
+    driver.quit()
+
+
+def test_name_of_logged_in_user(browser):
+    link = browser.find_element(By.XPATH, '//a[text()="Selenium Testbruker"]')
+    assert link is not None
+
+
+def test_admin_organisms(browser):
+    browser.find_element(By.XPATH, '//a[text()="Admin"]').click()
+    link = WebDriverWait(browser, 15).until(
+        EC.element_to_be_clickable((By.XPATH, '//a[text()="Organisms"]'))
+    )
+    assert link.get_attribute("href") == "http://localhost/organism"
+    link.click()
+    assert browser.title == "Organisms"
+    link = WebDriverWait(browser, 15).until(
+        EC.element_to_be_clickable((By.XPATH, '//a[text()="List all pests"]'))
+    )
+    link.click()
+    assert browser.title == "All pests"
+
+
+def test_admin_scheduling(browser):
+    browser.find_element(By.XPATH, '//a[text()="Admin"]').click()
+    link = WebDriverWait(browser, 10).until(
+        EC.element_to_be_clickable((By.XPATH, '//a[text()="Scheduling"]'))
+    )
+    assert link.get_attribute("href") == "http://localhost/scheduling"
+    link.click()
+    assert browser.title == "Scheduling overview"
+
+
+def test_admin_organization_group(browser):
+    browser.find_element(By.XPATH, '//a[text()="Admin"]').click()
+    link = WebDriverWait(browser, 10).until(
+        EC.element_to_be_clickable((By.XPATH, '//a[text()="Organization groups"]'))
+    )
+    assert link.get_attribute("href") == "http://localhost/organizationgroup"
+    link.click()
+    assert browser.title == "Organization groups"
+
+
+def test_admin_apple_fruit_moth(browser):
+    browser.find_element(By.XPATH, '//a[text()="Admin"]').click()
+    link = WebDriverWait(browser, 10).until(
+        EC.element_to_be_clickable((By.XPATH, '//a[text()="Apple fruit moth"]'))
+    )
+    assert link.get_attribute("href") == "http://localhost/applefruitmoth"
+    link.click()
+    assert browser.title == "Rognebærmøllstasjoner"