Skip to content

Commit

Permalink
feat(tests): rewrite
Browse files Browse the repository at this point in the history
Refactor code to make it easier to test a full deployment.

- leverage shUnit2's `setUp` and `tearDown` functions to setup a few things
- also introduce a `test::utils::setupFixture` function that copies a
  fixture into the container's HOME directory. This follows advice from
  shUnit2's developer: kward/shunit2#46
- add a more precise namespace to `test::` functions
- introduce new tests (`test::legacy::php8x`)
  • Loading branch information
Frzk committed Jan 25, 2024
1 parent 4f432a5 commit 029b020
Show file tree
Hide file tree
Showing 4 changed files with 195 additions and 124 deletions.
112 changes: 59 additions & 53 deletions test/helpers
Original file line number Diff line number Diff line change
Expand Up @@ -2,76 +2,82 @@

### Helpers functions

test::helpers::get_php_version() {
local old_home
test::helpers::test_deploy() {
# Deploy a PHP app in a Scalingo runtime and test that everything is as
# expected. The different fixtures allow us to test different setup and
# conditions.

old_home="${HOME}"
local fixture_name="${1}"
local detect_expectation="${2}"
local version="${3}"

HOME="/app"
export HOME
# Setup the fixture:
test::utils::setupFixture "${fixture_name}"

pushd "${HOME}" > /dev/null
# Test that bin/detect works as expected:
test::utils::detect
test::utils::assertCapturedSuccess
test::utils::assertCapturedEquals "${detect_expectation}"

cp --archive --recursive "${BUILD_DIR}"/* "${HOME}/"
# Test that bin/compile works as expected:
test::utils::compile
# We can't use assertCapturedSuccess here:
# With an empty composer.json file, composer will use stderr to warn us
# that nothing had to be installed, causing the test to fail for no
# reason -_-
test::utils::assertSuccess

test::utils::capture ./vendor/php/bin/php --version
# Switch environment:
test::helpers::enter_prod

# Test that PHP has the awaited version:
test::helpers::get_php_version
test::utils::assertCapturedStartswith "PHP ${version}"

popd > /dev/null
# Test that all default PHP modules are available:
test::helpers::list_php_modules
for module in "${default_modules[@]}"; do
test::utils::assertFileContains "${module}" "${STD_OUT}"
done
}

rm -Rf "${HOME}"/*
test::helpers::get_php_version() {
# Captures the output of `php --version` so we can check that the version
# installed is the expected one.

HOME="${old_home}"
export HOME
test::utils::capture ./vendor/php/bin/php --version
}

test::helpers::list_php_modules() {
local old_home
# Captures the output of `php --modules` so we can check that all default
# modules are indeed available.

test::utils::capture ./vendor/php/bin/php --modules
}

old_home="${HOME}"
test::helpers::enter_prod() {
# Helper to switch to a production-like environment:
# - $HOME is set to /app
# - Working directory is set to $HOME
# - The result of the `compile` script is copied to $HOME
#
# This environment is automatically reverted back, thanks to the `tearDown`
# function override in `test/run`.
# It would have been nice to put that in a `setUp` override. Unfortunately,
# we can't because the switch of environment should only happen **during**
# the test (after several steps have been reached), not before.
#
# /!\ This function is meant to be called after a successful call to
# to `test::utils::compile` to further test the result of the
# bin/compile call. It makes no sense to call it in another context.

PREV_HOME="${HOME}"
export PREV_HOME

HOME="/app"
export HOME

pushd "${HOME}" > /dev/null

cp --archive --recursive "${BUILD_DIR}"/* "${HOME}/"

test::utils::capture ./vendor/php/bin/php --modules

popd > /dev/null

rm -Rf "${HOME}"/*

HOME="${old_home}"
export HOME
}


test::helpers::test_compile() {
local fixture="${1}"
local php_version="${2}"

# PHP 8.0 is only available on stack `scalingo-20`:
[[ "${STACK}" != "scalingo-20" && "${php_version}" == "8.0." ]] \
&& echo "[skipping] PHP 8.0 is not available on scalingo-22" \
&& startSkipping

# Test that buildpack compiles:
test::utils::compile "${fixture}"
# We can't use assertCapturedSuccess here:
# Even with an empty composer.json file, composer will use stderr to warn
# us that nothing had to be installed, causing the test to fail for no
# reason -_-
test::utils::assertSuccess

# Test that we have the appropriate PHP version:
test::helpers::get_php_version
test::utils::assertCapturedStartswith "PHP ${php_version}"

# Test that all default PHP modules are present:
test::helpers::list_php_modules

for module in "${default_modules[@]}"; do
test::utils::assertFileContains "${module}" "${STD_OUT}"
done
}
23 changes: 19 additions & 4 deletions test/run
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,35 @@ oneTimeTearDown() {
}

setUp() {
export OUTPUT_DIR="$( mktemp --directory "${SHUNIT_TMPDIR}/output.XXXX" )"
OUTPUT_DIR="$( mktemp --directory "${SHUNIT_TMPDIR}/output.XXXX" )"

STD_OUT="${OUTPUT_DIR}/stdout"
STD_ERR="${OUTPUT_DIR}/stderr"

export BUILD_DIR="${OUTPUT_DIR}/build"
export CACHE_DIR="${OUTPUT_DIR}/cache"
export HOME="${BUILD_DIR}"
BUILD_DIR="${OUTPUT_DIR}/build"
CACHE_DIR="${OUTPUT_DIR}/cache"
HOME="${BUILD_DIR}"
BUILDPACK_DIR="$( mktemp --directory "/tmp/test-XXXXXX" )"

mkdir -p "${OUTPUT_DIR}" "${BUILD_DIR}" "${CACHE_DIR}"
export OUTPUT_DIR STD_OUT STD_ERR BUILD_DIR CACHE_DIR HOME BUILDPACK_DIR

# Copy the buildpack code into BUILDPACK_DIR:
cp --archive "$( pwd )"/* "${BUILDPACK_DIR}/"
}

tearDown() {
# Empty OUTPUT_DIR and BUILDPACK_DIR
rm -rf "${OUTPUT_DIR}"
rm -rf "${BUILDPACK_DIR}"

unset BUILDPACK_DIR BUILD_DIR CACHE_DIR PHP_VERSION

# We may have changed working dir, let's switch back to the initial one:
popd > /dev/null 2>&1

# Make sure /app is empty:
rm -rf "/app"/*
}

# Load shUnit2, which also run the tests:
Expand Down
123 changes: 94 additions & 29 deletions test/tests
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
source "$( pwd )/test/utils"
source "$( pwd )/test/helpers"

# List of modules that we want to ship with every PHP setup.
# For now, users can't specify a version for these modules, we just ship
# what we have. Hence no specific versions constraints here.
readonly default_modules=(
"apcu" "bcmath" "bz2" "Core" "ctype" "curl" "date" "dom" "exif" "fileinfo"
"filter" "gd" "hash" "iconv" "intl" "json" "libxml" "mbstring" "mongodb"
Expand All @@ -12,50 +15,112 @@ readonly default_modules=(
"tokenizer" "xml" "xmlreader" "xmlwriter" "xsl" "Zend OPcache" "zip" "zlib"
)

test::detect_legacy_default() {
# Test the buildpack detect script with a single simple .php file
test::utils::detect "legacy_default"
test::utils::assertCapturedSuccess
test::utils::assertCapturedEquals "PHP (classic)"

test::legacy::defaults() {
# Test a deployment of a legacy app (not using Composer)
# With default settings

test::helpers::test_deploy "legacy_default" "PHP (classic)" "8.1."
}

test::detect_composer_default() {
test::utils::detect "composer_default"
test::utils::assertCapturedSuccess
test::utils::assertCapturedEquals "PHP (composer.json)"
test::legacy::php80() {
# Test a deployment of a legacy app (not using Composer)
# Specifying we want PHP 8.0.x via environment

PHP_VERSION="8.0"
export PHP_VERSION

# PHP 8.0 is only available on stack `scalingo-20`:
if [[ "${STACK}" != "scalingo-20" ]]; then
echo "[skipping] PHP 8.0 is not available on scalingo-22"
startSkipping
fi

test::helpers::test_deploy "legacy_default" "PHP (classic)" "8.0."
}

test::compile_legacy_default() {
test::helpers::test_compile "legacy_default" "8.1."
test::legacy::php81() {
# Test a deployment of a legacy app (not using Composer)
# Specifying we want PHP 8.1.x via environment

PHP_VERSION="8.1"
export PHP_VERSION

test::helpers::test_deploy "legacy_default" "PHP (classic)" "8.1."
}

test::compile_composer_default() {
test::helpers::test_compile "composer_default" "8.1."
test::legacy::php82() {
# Test a deployment of a legacy app (not using Composer)
# Specifying we want PHP 8.2.x via environment

PHP_VERSION="8.2"
export PHP_VERSION

test::helpers::test_deploy "legacy_default" "PHP (classic)" "8.2."
}

test::compile_composer_php80() {
test::helpers::test_compile "composer_php80" "8.0."
test::legacy::php83() {
# Test a deployment of a legacy app (not using Composer)
# Specifying we want PHP 8.3.x via environment

PHP_VERSION="8.3"
export PHP_VERSION

test::helpers::test_deploy "legacy_default" "PHP (classic)" "8.3."
}

test::compile_composer_php81() {
test::helpers::test_compile "composer_php81" "8.1."
test::composer::defaults() {
# Test a deployment of a PHP app using Composer
# With default settings

test::helpers::test_deploy "composer_default" "PHP (composer.json)" "8.1."
}

test::compile_composer_php82() {
test::helpers::test_compile "composer_php82" "8.2."
test::composer::php80() {
# Test a deployment of a PHP app using Composer
# Specifying we want PHP 8.0.x in composer.json

# PHP 8.0 is only available on stack `scalingo-20`:
if [[ "${STACK}" != "scalingo-20" ]]; then
echo "[skipping] PHP 8.0 is not available on scalingo-22"
startSkipping
fi

test::helpers::test_deploy "composer_php80" "PHP (composer.json)" "8.0."
}

test::composer::php81() {
# Test a deployment of a PHP app using Composer
# Specifying we want PHP 8.1.x in composer.json

test::helpers::test_deploy "composer_php81" "PHP (composer.json)" "8.1."
}

test::compile_composer_php83() {
test::helpers::test_compile "composer_php83" "8.3."
test::composer::php82() {
# Test a deployment of a PHP app using Composer
# Specifying we want PHP 8.2.x in composer.json

test::helpers::test_deploy "composer_php82" "PHP (composer.json)" "8.2."
}

test::composer::php83() {
# Test a deployment of a PHP app using Composer
# Specifying we want PHP 8.3.x in composer.json

test::helpers::test_deploy "composer_php83" "PHP (composer.json)" "8.3."
}


# Add these functions to the test suite:

suite_addTest test::detect_legacy_default
suite_addTest test::compile_legacy_default
suite_addTest test::detect_composer_default
suite_addTest test::compile_composer_default
suite_addTest test::compile_composer_php80
suite_addTest test::compile_composer_php81
suite_addTest test::compile_composer_php82
suite_addTest test::compile_composer_php83
suite_addTest test::legacy::defaults
suite_addTest test::legacy::php80
suite_addTest test::legacy::php81
suite_addTest test::legacy::php82
suite_addTest test::legacy::php83

suite_addTest test::composer::defaults
suite_addTest test::composer::php80
suite_addTest test::composer::php81
suite_addTest test::composer::php82
suite_addTest test::composer::php83
Loading

0 comments on commit 029b020

Please sign in to comment.