2
0
mirror of https://github.com/frappe/frappe_docker.git synced 2025-01-10 00:37:53 +00:00

Refactor test

This commit is contained in:
Lev Vereshchagin 2022-02-08 15:49:14 +03:00
parent b2f63640ee
commit 7e562d7855

View File

@ -1,10 +1,12 @@
import os import os
import shlex
import shutil import shutil
import ssl import ssl
import subprocess import subprocess
import sys import sys
from enum import Enum from enum import Enum
from functools import wraps from functools import wraps
from textwrap import dedent
from time import sleep from time import sleep
from typing import Any, Callable, Optional from typing import Any, Callable, Optional
from urllib.error import HTTPError, URLError from urllib.error import HTTPError, URLError
@ -63,8 +65,13 @@ def log(text: str):
if CI: if CI:
print(f"::group::{text}") print(f"::group::{text}")
else: else:
print(colored(text, Color.YELLOW)) output = (
f"\n{f' {text} '.center(os.get_terminal_size().columns, '=')}\n"
)
print(colored(output, Color.YELLOW))
ret = f(*args, **kwargs) ret = f(*args, **kwargs)
if CI: if CI:
print("::endgroup::") print("::endgroup::")
return ret return ret
@ -75,7 +82,7 @@ def log(text: str):
def run(*cmd: str): def run(*cmd: str):
print(colored(f"> {' '.join(cmd)}", Color.GREEN)) print(colored(f"> {shlex.join(cmd)}", Color.GREEN))
return subprocess.check_call(cmd) return subprocess.check_call(cmd)
@ -101,7 +108,7 @@ def docker_compose(*cmd: str):
return run(*args, *cmd) return run(*args, *cmd)
def dco_exec(*cmd: str): def docker_compose_exec(*cmd: str):
if TTY: if TTY:
return docker_compose("exec", *cmd) return docker_compose("exec", *cmd)
else: else:
@ -111,25 +118,31 @@ def dco_exec(*cmd: str):
@log("Setup .env") @log("Setup .env")
def setup_env(): def setup_env():
shutil.copy("example.env", "tests/.env") shutil.copy("example.env", "tests/.env")
if not CI: if not CI:
return return
for env in ("FRAPPE_VERSION", "ERPNEXT_VERSION"):
if os.environ[env] == "develop": for var in ("FRAPPE_VERSION", "ERPNEXT_VERSION"):
if os.environ[var] == "develop":
with open(os.environ["GITHUB_ENV"], "a") as f: with open(os.environ["GITHUB_ENV"], "a") as f:
f.write(f"\n{env}=latest") f.write(f"\n{var}=latest")
os.environ[env] = "latest" os.environ[var] = "latest"
with open("tests/.env", "a") as f: with open("tests/.env", "a") as f:
f.write( f.write(
f""" dedent(
FRAPPE_VERSION={os.environ['FRAPPE_VERSION']} f"""
ERPNEXT_VERSION={os.environ['ERPNEXT_VERSION']} FRAPPE_VERSION={os.environ['FRAPPE_VERSION']}
""" ERPNEXT_VERSION={os.environ['ERPNEXT_VERSION']}
"""
)
) )
with open("tests/.env") as f: with open("tests/.env") as f:
print(f.read()) print(f.read())
@log("Print compose configuration") @log("Print configuration")
def print_compose_configuration(): def print_compose_configuration():
docker_compose("config") docker_compose("config")
@ -139,22 +152,22 @@ def create_containers():
docker_compose("up", "-d", "--quiet-pull") docker_compose("up", "-d", "--quiet-pull")
@log("Check if backend services have connections") @log("Check if Python services have connections")
def ping_links_in_backends(): def ping_links_in_backends():
for service in BACKEND_SERVICES: for service in BACKEND_SERVICES:
for _ in range(10): for _ in range(10):
try: try:
dco_exec(service, "healthcheck.sh") docker_compose_exec(service, "healthcheck.sh")
break break
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
sleep(1) sleep(1)
else: else:
raise Exception(f"Connections healthcheck failed for service {service}") raise RuntimeError(f"Connections healthcheck failed for service {service}")
@log("Create test site") @log("Create site")
def create_site(): def create_site():
dco_exec( docker_compose_exec(
"backend", "backend",
"bench", "bench",
"new-site", "new-site",
@ -176,14 +189,18 @@ _ssl_ctx.verify_mode = ssl.CERT_NONE
def ping_and_check_content(url: str, callback: Callable[[str], Optional[str]]): def ping_and_check_content(url: str, callback: Callable[[str], Optional[str]]):
request = Request(url, headers={"Host": SITE_NAME}) request = Request(url, headers={"Host": SITE_NAME})
print(f"Checking {url}") print(f"Checking {url}")
for _ in range(100): for _ in range(100):
try: try:
response = urlopen(request, context=_ssl_ctx) response = urlopen(request, context=_ssl_ctx)
except HTTPError as exc: except HTTPError as exc:
if exc.code not in (404, 502): if exc.code not in (404, 502):
raise raise
except URLError: except URLError:
pass pass
else: else:
text: str = response.read().decode() text: str = response.read().decode()
ret = callback(text) ret = callback(text)
@ -192,32 +209,33 @@ def ping_and_check_content(url: str, callback: Callable[[str], Optional[str]]):
return return
sleep(0.1) sleep(0.1)
raise AssertionError(f"Couldn't ping {url}")
raise RuntimeError(f"Couldn't ping {url}")
def index_callback(text: str): def check_index_callback(text: str):
if "404 page not found" not in text: if "404 page not found" not in text:
return text[:200] return text[:200]
@log("Check /") @log("Check /")
def check_index(): def check_index():
ping_and_check_content(url="http://127.0.0.1", callback=index_callback) ping_and_check_content("http://127.0.0.1", check_index_callback)
@log("Check /api/method/version") @log("Check /api/method/version")
def check_api(): def check_api():
ping_and_check_content( ping_and_check_content(
url="http://127.0.0.1/api/method/version", "http://127.0.0.1/api/method/version",
callback=lambda text: text if '"message"' in text else None, lambda text: text if '"message"' in text else None,
) )
@log("Check if Frappe can connect to services in backends") @log("Check if Frappe can connect to services in Python services")
def ping_frappe_connections_in_backends(): def ping_frappe_connections_in_backends():
for service in BACKEND_SERVICES: for service in BACKEND_SERVICES:
docker_compose("cp", "tests/_ping_frappe_connections.py", f"{service}:/tmp/") docker_compose("cp", "tests/_ping_frappe_connections.py", f"{service}:/tmp/")
dco_exec( docker_compose_exec(
service, service,
"/home/frappe/frappe-bench/env/bin/python", "/home/frappe/frappe-bench/env/bin/python",
f"/tmp/_ping_frappe_connections.py", f"/tmp/_ping_frappe_connections.py",
@ -227,8 +245,8 @@ def ping_frappe_connections_in_backends():
@log("Check /assets") @log("Check /assets")
def check_assets(): def check_assets():
ping_and_check_content( ping_and_check_content(
url="http://127.0.0.1/assets/frappe/images/frappe-framework-logo.svg", "http://127.0.0.1/assets/frappe/images/frappe-framework-logo.svg",
callback=lambda text: text[:200] if text is not None else None, lambda text: text[:200] if text else None,
) )
@ -241,8 +259,8 @@ def check_files():
f"backend:/home/frappe/frappe-bench/sites/{SITE_NAME}/public/files/", f"backend:/home/frappe/frappe-bench/sites/{SITE_NAME}/public/files/",
) )
ping_and_check_content( ping_and_check_content(
url=f"http://127.0.0.1/files/{file_name}", f"http://127.0.0.1/files/{file_name}",
callback=lambda text: text if text == "lalala\n" else None, lambda text: text if text == "lalala\n" else None,
) )
@ -265,7 +283,7 @@ def prepare_s3_server():
"/data", "/data",
) )
docker_compose("cp", "tests/_create_bucket.py", "backend:/tmp") docker_compose("cp", "tests/_create_bucket.py", "backend:/tmp")
dco_exec( docker_compose_exec(
"-e", "-e",
f"S3_ACCESS_KEY={S3_ACCESS_KEY}", f"S3_ACCESS_KEY={S3_ACCESS_KEY}",
"-e", "-e",
@ -278,8 +296,10 @@ def prepare_s3_server():
@log("Push backup to S3") @log("Push backup to S3")
def push_backup_to_s3(): def push_backup_to_s3():
dco_exec("backend", "bench", "--site", SITE_NAME, "backup", "--with-files") docker_compose_exec(
dco_exec( "backend", "bench", "--site", SITE_NAME, "backup", "--with-files"
)
docker_compose_exec(
"backend", "backend",
"push-backup", "push-backup",
"--site", "--site",
@ -297,10 +317,10 @@ def push_backup_to_s3():
) )
@log("Check backup in S3") @log("Check backup files in S3")
def check_backup_in_s3(): def check_backup_in_s3():
docker_compose("cp", "tests/_check_backup_files.py", "backend:/tmp") docker_compose("cp", "tests/_check_backup_files.py", "backend:/tmp")
dco_exec( docker_compose_exec(
"-e", "-e",
f"S3_ACCESS_KEY={S3_ACCESS_KEY}", f"S3_ACCESS_KEY={S3_ACCESS_KEY}",
"-e", "-e",
@ -316,14 +336,14 @@ def stop_s3_container():
run("docker", "rm", "minio", "-f") run("docker", "rm", "minio", "-f")
@log("Recreate with https override") @log("Recreate with HTTPS override")
def recreate_with_https_override(): def recreate_with_https_override():
docker_compose("-f", "overrides/compose.https.yaml", "up", "-d") docker_compose("-f", "overrides/compose.https.yaml", "up", "-d")
@log("Check / (https)") @log("Check / (HTTPS)")
def check_index_https(): def check_index_https():
ping_and_check_content(url="https://127.0.0.1", callback=index_callback) ping_and_check_content("https://127.0.0.1", check_index_callback)
@log("Stop containers") @log("Stop containers")
@ -335,13 +355,14 @@ def stop_containers():
def create_containers_with_erpnext_override(): def create_containers_with_erpnext_override():
args = ["-f", "overrides/compose.erpnext.yaml"] args = ["-f", "overrides/compose.erpnext.yaml"]
if CI: if CI:
args.extend(("-f", "tests/compose.ci-erpnext.yaml")) args += ("-f", "tests/compose.ci-erpnext.yaml")
docker_compose(*args, "up", "-d", "--quiet-pull") docker_compose(*args, "up", "-d", "--quiet-pull")
@log("Create ERPNext site") @log("Create ERPNext site")
def create_erpnext_site(): def create_erpnext_site():
dco_exec( docker_compose_exec(
"backend", "backend",
"bench", "bench",
"new-site", "new-site",
@ -356,19 +377,19 @@ def create_erpnext_site():
docker_compose("restart", "backend") docker_compose("restart", "backend")
@log("Check /api/method/erpnext.templates.pages.product_search.get_product_list") @log("Check /api/method")
def check_erpnext_api(): def check_erpnext_api():
ping_and_check_content( ping_and_check_content(
url="http://127.0.0.1/api/method/erpnext.templates.pages.product_search.get_product_list", "http://127.0.0.1/api/method/erpnext.templates.pages.product_search.get_product_list",
callback=lambda text: text if '"message"' in text else None, lambda text: text if '"message"' in text else None,
) )
@log("Check /assets/erpnext/js/setup_wizard.js") @log("Check /assets")
def check_erpnext_assets(): def check_erpnext_assets():
ping_and_check_content( ping_and_check_content(
url="http://127.0.0.1/assets/erpnext/js/setup_wizard.js", "http://127.0.0.1/assets/erpnext/js/setup_wizard.js",
callback=lambda text: text[:200] if text is not None else None, lambda text: text[:200] if text else None,
) )
@ -379,9 +400,11 @@ def create_containers_with_postgres_override():
@log("Create Postgres site") @log("Create Postgres site")
def create_postgres_site(): def create_postgres_site():
dco_exec("backend", "bench", "set-config", "-g", "root_login", "postgres") docker_compose_exec(
dco_exec("backend", "bench", "set-config", "-g", "root_password", "123") "backend", "bench", "set-config", "-g", "root_login", "postgres"
dco_exec( )
docker_compose_exec("backend", "bench", "set-config", "-g", "root_password", "123")
docker_compose_exec(
"backend", "backend",
"bench", "bench",
"new-site", "new-site",
@ -399,52 +422,76 @@ def delete_env():
os.remove("tests/.env") os.remove("tests/.env")
@log("Show docker compose logs") @log("Show logs")
def show_docker_compose_logs(): def show_docker_compose_logs():
docker_compose("logs") docker_compose("logs")
def start():
setup_env()
print_compose_configuration()
create_containers()
ping_links_in_backends()
def create_frappe_site_and_check_availability():
create_site()
check_index()
check_api()
ping_frappe_connections_in_backends()
check_assets()
check_files()
def check_s3():
prepare_s3_server()
try:
push_backup_to_s3()
check_backup_in_s3()
finally:
stop_s3_container()
def check_https():
print_compose_configuration()
recreate_with_https_override()
check_index_https()
stop_containers()
def check_erpnext():
print_compose_configuration()
create_containers_with_erpnext_override()
create_erpnext_site()
check_erpnext_api()
check_erpnext_assets()
stop_containers()
def check_postgres():
print_compose_configuration()
create_containers_with_postgres_override()
create_postgres_site()
ping_links_in_backends()
def main() -> int: def main() -> int:
try: try:
patch_print() patch_print()
start()
setup_env() create_frappe_site_and_check_availability()
print_compose_configuration() check_s3()
create_containers() check_https()
check_erpnext()
ping_links_in_backends() check_postgres()
create_site()
check_index()
check_api()
ping_frappe_connections_in_backends()
check_assets()
check_files()
prepare_s3_server()
push_backup_to_s3()
check_backup_in_s3()
stop_s3_container()
recreate_with_https_override()
check_index_https()
stop_containers()
create_containers_with_erpnext_override()
create_erpnext_site()
check_erpnext_api()
check_erpnext_assets()
stop_containers()
create_containers_with_postgres_override()
create_postgres_site()
ping_links_in_backends()
finally: finally:
delete_env() delete_env()
show_docker_compose_logs() show_docker_compose_logs()
stop_containers() stop_containers()
print(colored("Tests successfully passed!", Color.YELLOW)) print(colored("\nTests successfully passed!", Color.YELLOW))
return 0 return 0