Skip to content

Commit

Permalink
Use pytest (#705)
Browse files Browse the repository at this point in the history
* Use pytest for tests

* Pin black

* Update CI

* Rename test_main to test_frappe_docker

* Force project name "test"
  • Loading branch information
vrslev authored Mar 24, 2022
1 parent 1d5a085 commit 41ba718
Show file tree
Hide file tree
Showing 12 changed files with 464 additions and 555 deletions.
23 changes: 14 additions & 9 deletions .github/workflows/docker-build-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,11 @@ jobs:
- name: Checkout
uses: actions/checkout@v3

- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: 3.9

- name: Setup Buildx
uses: docker/setup-buildx-action@v1
with:
driver-opts: network=host

- name: Install Docker Compose v2
uses: ndeloof/install-compose-action@4a33bc31f327b8231c4f343f6fba704fedc0fa23

- name: Get latest versions
run: python3 ./.github/scripts/get_latest_tags.py --repo ${{ inputs.repo }} --version ${{ inputs.version }}

Expand All @@ -57,8 +49,21 @@ jobs:
env:
REGISTRY_USER: localhost:5000/frappe

- name: Setup Python
uses: actions/setup-python@v3
with:
python-version: 3.9

- name: Install Docker Compose v2
uses: ndeloof/install-compose-action@4a33bc31f327b8231c4f343f6fba704fedc0fa23

- name: Install dependencies
run: |
python -m venv venv
venv/bin/pip install -r requirements-test.txt
- name: Test
run: python3 tests/main.py
run: pytest

- name: Login
if: ${{ inputs.push }}
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
frappe @ git+git://github.com/frappe/frappe.git
boto3-stubs[s3]
black==22.1.0
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest==7.1.0
3 changes: 3 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,6 @@ known_third_party = frappe

[codespell]
skip = images/bench/Dockerfile

[tool:pytest]
addopts = -s --exitfirst
Empty file added tests/__init__.py
Empty file.
50 changes: 50 additions & 0 deletions tests/_check_connections.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import asyncio
import json
import socket
from typing import Any, Iterable

Address = tuple[str, int]


async def wait_for_port(address: Address) -> None:
# From https://github.com/clarketm/wait-for-it
while True:
try:
_, writer = await asyncio.open_connection(*address)
writer.close()
await writer.wait_closed()
break
except (socket.gaierror, ConnectionError, OSError, TypeError):
pass
await asyncio.sleep(0.1)


def get_redis_url(addr: str) -> Address:
result = addr.replace("redis://", "")
result = result.split("/")[0]
parts = result.split(":")
assert len(parts) == 2
return parts[0], int(parts[1])


def get_addresses(config: dict[str, Any]) -> Iterable[Address]:
yield (config["db_host"], config["db_port"])
for key in ("redis_cache", "redis_queue", "redis_socketio"):
yield get_redis_url(config[key])


async def async_main(addresses: set[Address]) -> None:
tasks = [asyncio.wait_for(wait_for_port(addr), timeout=5) for addr in addresses]
await asyncio.gather(*tasks)


def main() -> int:
with open("/home/frappe/frappe-bench/sites/common_site_config.json") as f:
config = json.load(f)
addresses = set(get_addresses(config))
asyncio.run(async_main(addresses))
return 0


if __name__ == "__main__":
raise SystemExit(main())
152 changes: 152 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
import os
import shutil
import subprocess
from dataclasses import dataclass
from pathlib import Path

import pytest

from tests.utils import CI, Compose


def _add_version_var(name: str, env_path: Path):
if not os.getenv(name):
return

if (gh_env := os.getenv("GITHUB_ENV")) and os.environ[name] == "develop":
with open(gh_env, "a") as f:
f.write(f"\n{name}=latest")

os.environ[name] = "latest"

with open(env_path, "a") as f:
f.write(f"\n{name}={os.environ[name]}")


@pytest.fixture(scope="session")
def env_file(tmp_path_factory: pytest.TempPathFactory):
tmp_path = tmp_path_factory.mktemp("frappe-docker")
file_path = tmp_path / ".env"
shutil.copy("example.env", file_path)

for var in ("FRAPPE_VERSION", "ERPNEXT_VERSION"):
_add_version_var(name=var, env_path=file_path)

yield file_path
os.remove(file_path)


@pytest.fixture(scope="session")
def compose(env_file: str):
return Compose(project_name="test", env_file=env_file)


@pytest.fixture(autouse=True, scope="session")
def frappe_setup(compose: Compose):
compose.stop()
compose("up", "-d", "--quiet-pull")
yield
compose.stop()


@pytest.fixture(scope="session")
def frappe_site(compose: Compose):
site_name = "tests"
compose.bench(
"new-site",
site_name,
"--mariadb-root-password",
"123",
"--admin-password",
"admin",
)
compose("restart", "backend")
yield site_name


@pytest.fixture(scope="class")
def erpnext_setup(compose: Compose):
compose.stop()

args = ["-f", "overrides/compose.erpnext.yaml"]
if CI:
args += ("-f", "tests/compose.ci-erpnext.yaml")
compose(*args, "up", "-d", "--quiet-pull")

yield
compose.stop()


@pytest.fixture(scope="class")
def erpnext_site(compose: Compose):
site_name = "test_erpnext_site"
compose.bench(
"new-site",
site_name,
"--mariadb-root-password",
"123",
"--admin-password",
"admin",
"--install-app",
"erpnext",
)
compose("restart", "backend")
yield site_name


@pytest.fixture
def postgres_setup(compose: Compose):
compose.stop()
compose("-f", "overrides/compose.postgres.yaml", "up", "-d", "--quiet-pull")
compose.bench("set-config", "-g", "root_login", "postgres")
compose.bench("set-config", "-g", "root_password", "123")
yield
compose.stop()


@pytest.fixture
def python_path():
return "/home/frappe/frappe-bench/env/bin/python"


@dataclass
class S3ServiceResult:
access_key: str
secret_key: str


@pytest.fixture
def s3_service(python_path: str, compose: Compose):
access_key = "AKIAIOSFODNN7EXAMPLE"
secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
cmd = (
"docker",
"run",
"--name",
"minio",
"-d",
"-e",
f"MINIO_ACCESS_KEY={access_key}",
"-e",
f"MINIO_SECRET_KEY={secret_key}",
"--network",
f"{compose.project_name}_default",
"minio/minio",
"server",
"/data",
)
subprocess.check_call(cmd)

compose("cp", "tests/_create_bucket.py", "backend:/tmp")
compose.exec(
"-e",
f"S3_ACCESS_KEY={access_key}",
"-e",
f"S3_SECRET_KEY={secret_key}",
"backend",
python_path,
"/tmp/_create_bucket.py",
)

yield S3ServiceResult(access_key=access_key, secret_key=secret_key)
subprocess.call(("docker", "rm", "minio", "-f"))
28 changes: 0 additions & 28 deletions tests/healthcheck.sh

This file was deleted.

Loading

0 comments on commit 41ba718

Please sign in to comment.