Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Install test requirements on startup #115

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/assets/docker_compose.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ DEV_SOURCE_PATH=pulpcore:pulp_file
COMPOSE_BINARY=docker
SECOND_SERVICE_PORT=8002
CUSTOM_DEFAULT2=howdy_default
INSTALL_TESTS=True
1 change: 1 addition & 0 deletions .github/assets/podman_compose.env
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ DEV_SOURCE_PATH=pulpcore:pulp_file
COMPOSE_BINARY=podman
SECOND_SERVICE_PORT=8002
CUSTOM_DEFAULT2=howdy_default
INSTALL_TESTS=True
12 changes: 9 additions & 3 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ jobs:
if: matrix.TEST == 'docker' && matrix.os == 'macos-12'
uses: docker-practice/actions-setup-docker@1.0.11

- name: Install dependencies for docker
if: matrix.TEST == 'docker' && matrix.os == 'ubuntu-latest'
run: |
sudo apt update
sudo apt install -y httpie

- name: setup .compose.env files
run: |
cp oci_env/.github/assets/${TEST}_compose.env oci_env/compose.env
Expand All @@ -91,8 +97,8 @@ jobs:

- name: Wait for the stack to spin up
run: |
oci-env poll --wait 15 --attempts 30
oci-env -e custom.env poll --wait 5 --attempts 5
oci-env poll --wait 15 --attempts 100
oci-env -e custom.env poll --wait 5 --attempts 100

- name: Create some dummy data with the pulp CLI (retry up to 5 times because it's sometimes not actually ready)
run: for i in $(seq 1 5); do oci-env pulp file repository create --name test1 && s=0 && break || s=$? && sleep 5; done; (exit $s)
Expand Down Expand Up @@ -128,7 +134,7 @@ jobs:
- name: Test functional tests
run: |
oci-env -v generate-client -i
oci-env -v test -i -p pulp_file functional -k test_labels
oci-env -v test -p pulp_file functional -k test_labels

- name: Test lint
run: oci-env -v test -i -p pulp_file lint
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,14 +139,21 @@ oci-env -e custom.env compose up

## Running Tests

Test dependencies are automatically installed after the container startup when you set the `INSTALL_TESTS` variable to `True` in the compose file.

### Lint

```bash
# Re-install all test requirements for all plugins

oci-env test -i

# Install the lint requirements and run the linter for a specific plugin

oci-env test -i -p PLUGIN_NAME lint

# Run the linter without installing lint dependencies.
# Run the linter without installing lint dependencies

oci-env test -p PLUGIN_NAME lint
```

Expand Down
2 changes: 1 addition & 1 deletion base/container_scripts/install_lint_requirements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ fi
cd "/src/$PROJECT/"

if [[ -f lint_requirements.txt ]]; then
pip install -r lint_requirements.txt
pip3 install -r lint_requirements.txt
fi
4 changes: 2 additions & 2 deletions base/container_scripts/install_performance_requirements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fi
cd "/src/$PROJECT/"

if [[ -f perftest_requirements.txt ]]; then
pip install -r perftest_requirements.txt
pip3 install -r perftest_requirements.txt
elif [[ -f functest_requirements.txt ]]; then
pip install -r functest_requirements.txt
pip3 install -r functest_requirements.txt
fi
29 changes: 29 additions & 0 deletions base/container_scripts/install_test_requirements.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import os
import subprocess

from django.conf import settings

projects = os.getenv("DEV_SOURCE_PATH").split(":")

# load django settings on the fly
settings.DYNACONF.configure()
api_root = settings.get("API_ROOT")


test_requirements_scripts = [
"install_functional_requirements.sh",
"install_performance_requirements.sh",
"install_unit_requirements.sh",
"install_lint_requirements.sh",
]

for project in projects:
print(f"Installing test requirements for {project}...")
for test_script in test_requirements_scripts:
test_script = os.path.join("/opt/oci_env/base/container_scripts/", test_script)
print(f"Running {test_script} for {project}...")

try:
subprocess.run(["bash", test_script, project], capture_output=False)
except subprocess.CalledProcessError as err:
print(test_script, project, err.stdout)
2 changes: 1 addition & 1 deletion base/container_scripts/install_unit_requirements.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ pip install git+https://github.com/pulp/pulp-smash.git
cd "/src/$PROJECT/"

if [[ -f unittest_requirements.txt ]]; then
pip install -r unittest_requirements.txt
pip3 install -r unittest_requirements.txt
fi
8 changes: 8 additions & 0 deletions base/container_scripts/run_functional_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,19 @@ EOF
}
}

function check_test () {
[[ -d "${PROJECT}/tests/functional" ]] || {
echo "Skipping functional tests because they do not seem to exist..."
exit 0
}
}

source "/opt/oci_env/base/container_scripts/configure_pulp_smash.sh"

cd "/src/$PACKAGE/"

check_pytest
check_client
check_test

sudo -u pulp -E pytest -r sx --rootdir=/var/lib/pulp --color=yes --pyargs "$PROJECT.tests.functional" "${@:2}"
8 changes: 8 additions & 0 deletions base/container_scripts/run_performance_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,19 @@ EOF
}
}

function check_test () {
[[ -d "${PROJECT}/tests/performance" ]] || {
echo "Skipping performance tests because they do not seem to exist..."
exit 0
}
}

source "/opt/oci_env/base/container_scripts/configure_pulp_smash.sh"

cd "/src/$PACKAGE/"

check_pytest
check_client
check_test

sudo -u pulp -E pytest -r sx --rootdir=/var/lib/pulp --color=yes --pyargs "$PROJECT.tests.performance" "${@:2}"
10 changes: 10 additions & 0 deletions base/container_scripts/run_unit_tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,18 @@ declare PROJECT="${PACKAGE//-/_}"

set -e

function check_test () {
[[ -d "${PROJECT}/tests/unit" ]] || {
echo "Skipping unit tests because they do not seem to exist..."
pwd
exit 0
}
}

source "/opt/oci_env/base/container_scripts/configure_pulp_smash.sh"

cd "/src/$PACKAGE/"

check_test

sudo -u pulp -E PULP_DATABASES__default__USER=postgres pytest -r sx --color=yes --pyargs "$PROJECT.tests.unit" "${@:2}"
23 changes: 22 additions & 1 deletion base/utils.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ set -o pipefail

readonly DEV_SOURCE_PATH="${DEV_SOURCE_PATH:-}"
readonly LOCK_REQUIREMENTS="${LOCK_REQUIREMENTS:-1}"
readonly INSTALL_TESTS="${INSTALL_TESTS:-False}"


log_message() {
Expand Down Expand Up @@ -36,6 +37,25 @@ install_local_deps() {
done
}

install_test_deps() {
if [ "$INSTALL_TESTS" = "True" ]; then
local src_path_list
IFS=':' read -ra src_path_list <<< "$DEV_SOURCE_PATH"

for item in "${src_path_list[@]}"; do
src_path="/src/${item}"
if [[ -d "$src_path" ]]; then
log_message "Installing requirements for ${item}."
pip3 install -r "${src_path}"/lint_requirements.txt || true
pip3 install -r "${src_path}"/unittest_requirements.txt || true
pip3 install -r "${src_path}"/functest_requirements.txt || true
pip3 install -r "${src_path}"/perftest_requirements.txt || true
fi
done
# python3 /opt/oci_env/base/container_scripts/install_test_requirements.py
fi
}

create_super_user() {
pulpcore-manager createsuperuser --no-input --email admin@example.com
}
Expand All @@ -55,10 +75,11 @@ set_nginx_port() {
init_container() {
install_local_deps
set_nginx_port
install_test_deps
}

run_profile_init_scripts() {
bash /opt/oci_env/.compiled/${COMPOSE_PROJECT_NAME}/init.sh
}

$1
$1
82 changes: 60 additions & 22 deletions client/oci_env/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,36 +67,74 @@ def shell(args, client):


def test(args, client):
if args.install_deps:
test_script = f"install_{args.test}_requirements.sh"
tr = TestRunner(args, client)
tr.install_requirements()
tr.run_tests()

if args.plugin:
exit_if_failed(
client.exec_container_script(
test_script,
args=[args.plugin],
privileged=args.privileged,
).returncode
)
else:
for project in client.config["DEV_SOURCE_PATH"].split(":"):

class TestRunner:
test_requirements_scripts = [
"install_functional_requirements.sh",
"install_performance_requirements.sh",
"install_unit_requirements.sh",
"install_lint_requirements.sh",
]

test_run_scripts = [
"run_functional_tests.sh",
"run_performance_tests.sh",
"run_unit_tests.sh",
"run_lint_tests.sh",
]

def __init__(self, args, client):
self.args = args
self.client = client
self.projects = client.config["DEV_SOURCE_PATH"].split(":")

def install_requirements(self):
if self.args.install_deps:
if self.args.test != "all":
test_script = f"install_{self.args.test}_requirements.sh"
if self.args.plugin:
self.install_test_requirements([self.args.plugin], [test_script])
else:
self.install_test_requirements(self.projects, [test_script])
else:
if self.args.plugin:
self.install_test_requirements([self.args.plugin], self.test_requirements_scripts)
else:
self.install_test_requirements(self.projects, self.test_requirements_scripts)

def install_test_requirements(self, projects, test_requirements_scripts):
for project in projects:
for test_script in test_requirements_scripts:
print(f"Running {test_script} for {project}...")
exit_if_failed(
client.exec_container_script(
self.client.exec_container_script(
test_script,
args=[project],
privileged=args.privileged,
privileged=self.args.privileged,
).returncode
)

if args.plugin:
exit_if_failed(
client.exec_container_script(
f"run_{args.test}_tests.sh",
args=[args.plugin] + args.args,
interactive=True,
privileged=args.privileged,
def run_tests(self):
if self.args.plugin:
if self.args.test != "all":
self.run_test_command(self.args.plugin, [f"run_{self.args.test}_tests.sh"])
else:
self.run_test_command(self.args.plugin, self.test_run_scripts)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has to be a manual check on which types of tests the given plugin implements. For example, running all types of tests on pulpcore only runs functional tests and fails on performance tests (since there are none to be run), without a chance to start the remaining (unit, lint) tests.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! 🐶

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will adjust the scripts to assert the presence of the tests before running them.

function check_test() {
   if ![ -d "/path/dir/" ] ...
}

check_test


def run_test_command(self, project, tests):
for test_script in tests:
exit_if_failed(
self.client.exec_container_script(
test_script,
args=[project] + self.args.args,
interactive=True,
privileged=self.args.privileged,
)
)
)


def generate_client(args, client):
Expand Down
2 changes: 1 addition & 1 deletion client/oci_env/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def parse_shell_command(subparsers):

def parse_test_command(subparsers):
parser = subparsers.add_parser('test', help='Run tests and install requirements.')
parser.add_argument('test', choices=["functional", "unit", "lint", "performance"])
parser.add_argument('test', choices=["functional", "unit", "lint", "performance", "all"], nargs="?", default="all")
parser.add_argument('-i', action='store_true', dest='install_deps', help="Install the python dependencies for the selected test instead of running it. If -p is not specified this will install all the test dependencies for each plugin in DEV_SOURCE_PATH.")
parser.add_argument('-p', type=str, default="", dest='plugin', help="Plugin to test. Tests won't run unless this is specified.")
parser.add_argument('args', nargs=argparse.REMAINDER, help='Arguments to pass to pytest.')
Expand Down
3 changes: 3 additions & 0 deletions client/oci_env/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ def get_config(env_file):
# Directory on the host where the DEV_SOURCE_PATH projects are checked out
"SRC_DIR": os.path.abspath(os.path.join(path, "..")),

# Install tests automatically on startup
"INSTALL_TESTS": "False",

# List of : separated profiles to use
"COMPOSE_PROFILE": "",

Expand Down
3 changes: 3 additions & 0 deletions compose.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ COMPOSE_PROFILE=
# : separate list of python dependencies to include from source
DEV_SOURCE_PATH=

# Install test dependencies automatically
# INSTALL_TESTS=False
#
# Program to use for compose. This defaults to podman. Uncomment this to use docker-compose.
# COMPOSE_BINARY=docker

Expand Down