From 6894d22e6c045449728f239eee8585a163710932 Mon Sep 17 00:00:00 2001 From: Simon Adorf Date: Fri, 5 Aug 2022 14:35:52 +0200 Subject: [PATCH] Implement tests. --- .github/workflows/build_and_test_on_pr.yml | 30 +++---------- tests/conftest.py | 50 ++++++++++++++++++++++ tests/docker-compose.yml | 46 ++++++++++++++++++++ tests/requirements.txt | 4 ++ tests/test_lab.py | 26 +++++++++++ 5 files changed, 133 insertions(+), 23 deletions(-) create mode 100644 tests/conftest.py create mode 100644 tests/docker-compose.yml create mode 100644 tests/requirements.txt create mode 100644 tests/test_lab.py diff --git a/.github/workflows/build_and_test_on_pr.yml b/.github/workflows/build_and_test_on_pr.yml index 1f035924..32e74b07 100644 --- a/.github/workflows/build_and_test_on_pr.yml +++ b/.github/workflows/build_and_test_on_pr.yml @@ -40,27 +40,11 @@ jobs: tags: aiidalab-docker-stack:latest cache-from: type=local,src=/tmp/.buildx-cache cache-to: type=local,dest=/tmp/.buildx-cache - - name: Start and test the container - id: test_run + - uses: actions/setup-python@v4 + with: + python-version: '3.10' + cache: pip # caching pip dependencies + - run: pip install -r tests/requirements.txt + - name: Run tests run: | - mkdir tmp - export DOCKERID=`docker run -v $PWD/tmp:/home/aiida -d aiidalab-docker-stack:latest` - echo "::set-output name=docker_id_first_run::${DOCKERID}" - docker exec --tty --user root $DOCKERID wait-for-services - docker exec --tty --user aiida $DOCKERID wait-for-services - docker exec --tty --user aiida $DOCKERID /bin/bash -l -c '/usr/lib/postgresql/10/bin/pg_ctl -D /home/$NB_USER/.postgresql status' # Check that postgres is up. - docker exec --tty --user root $DOCKERID /bin/bash -l -c 'service rabbitmq-server status' # Check that rabbitmq is up. - docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'conda create -y -n test_env python=3.8' # Check that one can create a new conda environment. - docker exec --tty --user aiida $DOCKERID /bin/bash -l -c 'conda activate test_env' # Check that new environment works. - sudo cp tmp/.ssh/id_rsa . # Copy id_rsa file from the mounted folder. - docker stop $DOCKERID # Stop the container. - export DOCKERID=`docker run -v $PWD/tmp:/home/aiida -d aiidalab-docker-stack:latest` # Start a new container using the same mounted folder. - echo "::set-output name=docker_id_second_run::${DOCKERID}" - docker exec --tty $DOCKERID wait-for-services - sudo diff id_rsa tmp/.ssh/id_rsa # Check that the id_rsa file wasn't modified. - - name: Show the container log (first run). - if: always() - run: docker logs "${{ steps.test_run.outputs.docker_id_first_run }}" - - name: Show the container log (second run). - if: always() - run: docker logs "${{ steps.test_run.outputs.docker_id_second_run }}" + pytest -v diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..62bc9197 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,50 @@ +import pytest +import requests + +from requests.exceptions import ConnectionError + + +def is_responsive(url): + try: + response = requests.get(url) + if response.status_code == 200: + return True + except ConnectionError: + return False + + +@pytest.fixture(scope="session") +def notebook_service(docker_ip, docker_services): + """Ensure that HTTP service is up and responsive.""" + port = docker_services.port_for("lab", 8888) + url = f"http://{docker_ip}:{port}" + docker_services.wait_until_responsive( + timeout=30.0, pause=0.1, check=lambda: is_responsive(url) + ) + return url + + +@pytest.fixture(scope="session") +def docker_compose(docker_services): + return docker_services._docker_compose + + +@pytest.fixture +def lab_exec(docker_compose): + def execute(command, user=None, **kwargs): + if user: + command = f"exec -T --user={user} lab {command}" + else: + command = f"exec -T lab {command}" + return docker_compose.execute(command, **kwargs) + + return execute + + +@pytest.fixture +def nb_user(docker_compose): + return ( + docker_compose.execute("exec -T lab bash -c 'echo \"$NB_USER\"'") + .decode() + .strip() + ) diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100644 index 00000000..967f00d3 --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,46 @@ +--- +version: '3.4' + +services: + + database: + image: postgres:12.3 + #container_name: aiida-database + environment: + POSTGRES_USER: pguser + POSTGRES_PASSWORD: password + volumes: + - aiida-postgres-db:/var/lib/postgresql/data + restart: always + + messaging: + image: rabbitmq:3.8.3-management + #container_name: aiida-rmq + environment: + RABBITMQ_DEFAULT_USER: guest + RABBITMQ_DEFAULT_PASS: guest + volumes: + - aiida-rmq-data:/var/lib/rabbitmq/ + restart: always + + lab: + image: aiidalab-docker-stack:latest + environment: + RMQHOST: messaging + TZ: Europe/Zurich + DOCKER_STACKS_JUPYTER_CMD: notebook + SETUP_DEFAULT_AIIDA_PROFILE: 'true' + AIIDALAB_DEFAULT_APPS: '' + volumes: + - aiidalab-home-folder:/home/jovyan + depends_on: + - database + - messaging + ports: + - 8888:8888 + + +volumes: + aiida-postgres-db: + aiida-rmq-data: + aiidalab-home-folder: diff --git a/tests/requirements.txt b/tests/requirements.txt new file mode 100644 index 00000000..ade94cbc --- /dev/null +++ b/tests/requirements.txt @@ -0,0 +1,4 @@ +docker-compose==1.29.2 +pytest==7.1.2 +pytest-docker==1.0.0 +requests==2.28.1 diff --git a/tests/test_lab.py b/tests/test_lab.py new file mode 100644 index 00000000..b62ae0d8 --- /dev/null +++ b/tests/test_lab.py @@ -0,0 +1,26 @@ +import requests + + +def test_notebook_service_available(notebook_service): + response = requests.get(f"{notebook_service}/") + assert response.status_code == 200 + + +def test_pip_check(lab_exec): + lab_exec("pip check") + + +def test_aiidalab_available(lab_exec, nb_user): + output = lab_exec("aiidalab --version", user=nb_user).decode().strip().lower() + assert "aiidalab" in output + + +def test_create_conda_environment(lab_exec, nb_user): + output = lab_exec("conda create -y -n tmp", user=nb_user).decode().strip() + assert "conda activate tmp" in output + + +def test_verdi_status(lab_exec, nb_user): + output = lab_exec("verdi status", user=nb_user).decode().strip() + assert "Connected to RabbitMQ" in output + assert "Daemon is running" in output