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

Streamline local test environment setup #916

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
build/ export-ignore
docs/ export-ignore
examples/ export-ignore
scripts/ export-ignore
tests/ export-ignore
.codecov.yml export-ignore
.editorconfig export-ignore
Expand Down
69 changes: 53 additions & 16 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,8 @@ Code coverage is monitored for every PR and for the code base as a whole using [

- [PHP][] >= 5.6
- [Composer][]
- [Python 3][]
- [mitmproxy][] (`pip3 install mitmproxy`)
- [Python 3][] >= 3.12
- [mitmproxy][] >= 11.0.2 (`pip3 install mitmproxy`)

[PHP]: https://www.php.net/
[Composer]: http://getcomposer.org/
Expand All @@ -109,28 +109,65 @@ Code coverage is monitored for every PR and for the code base as a whole using [

### Running the Tests

schlessera marked this conversation as resolved.
Show resolved Hide resolved
There are several ways to run the tests locally:

#### 1. Using Composer Scripts (Recommended)

The simplest way to run tests is using the Composer scripts:

```bash
# Run tests without coverage
composer test

# Run tests with coverage
composer coverage

# Run tests with automatic test server management
composer test:withserver
```

#### 2. Manual Test Environment Management

If you need more control over the test environment, you can manage it manually:

```bash
# Start all test servers and set environment variables
# We need to source the script to properly set environment variables in our shell
source scripts/start-test-environment.sh

# Now run your tests
composer test

# When done, stop all servers
./scripts/stop-test-environment.sh
```

Note: The environment scripts must be sourced (using `source` or `.`) to properly set environment variables in your shell.

#### 3. Individual Component Control

For debugging or development, you might want to manage individual components:

```bash
# Start the test server
# Start only the test server
PORT=8080 vendor/bin/start.sh
export "REQUESTS_TEST_HOST_HTTP=localhost:8080"
export REQUESTS_TEST_HOST_HTTP=localhost:8080

# Start the proxy server
# Start only the proxy servers
PORT=9002 tests/utils/proxy/start.sh
PORT=9003 AUTH="test:pass" tests/utils/proxy/start.sh
export "REQUESTS_HTTP_PROXY=localhost:9002"
export "REQUESTS_HTTP_PROXY_AUTH=localhost:9003"
export "REQUESTS_HTTP_PROXY_AUTH_USER=test"
export "REQUESTS_HTTP_PROXY_AUTH_PASS=pass"
export REQUESTS_HTTP_PROXY=localhost:9002
export REQUESTS_HTTP_PROXY_AUTH=localhost:9003
export REQUESTS_HTTP_PROXY_AUTH_USER=test
export REQUESTS_HTTP_PROXY_AUTH_PASS=pass
```

# Run the tests
composer test
schlessera marked this conversation as resolved.
Show resolved Hide resolved
Remember to stop any servers you start:

# Stop the proxy server
PORT=9002 tests/utils/proxy/stop.sh
```bash
vendor/bin/stop.sh # Stop test server
PORT=9002 tests/utils/proxy/stop.sh # Stop proxy servers
PORT=9003 tests/utils/proxy/stop.sh

# Stop the test server
vendor/bin/stop.sh
```

To run the test with code coverage, use `composer coverage` instead.
Expand Down
11 changes: 1 addition & 10 deletions .github/workflows/quicktest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -90,18 +90,9 @@ jobs:
- name: Access localhost on port 9002
run: curl -i http://localhost:9002

- name: Grab PHPUnit version
id: phpunit_version
run: echo "VERSION=$(vendor/bin/phpunit --version | grep --only-matching --max-count=1 --extended-regexp '\b[0-9]+\.[0-9]+')" >> "$GITHUB_OUTPUT"

- name: Run the unit tests (PHPUnit < 10)
if: ${{ ! startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
- name: Run the unit tests
run: composer test

- name: Run the unit tests (PHPUnit 10+)
if: ${{ startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
run: composer test10

- name: Stop proxy server
continue-on-error: true
run: |
Expand Down
20 changes: 4 additions & 16 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,26 +114,14 @@ jobs:
- name: Access localhost on port 9002
run: curl -i http://localhost:9002

- name: Grab PHPUnit version
id: phpunit_version
run: echo "VERSION=$(vendor/bin/phpunit --version | grep --only-matching --max-count=1 --extended-regexp '\b[0-9]+\.[0-9]+')" >> "$GITHUB_OUTPUT"

- name: Run the unit tests, no code coverage (PHPUnit < 10)
if: ${{ matrix.coverage == false && ! startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
- name: Run the unit tests, no code coverage
if: ${{ matrix.coverage == false }}
run: composer test

- name: Run the unit tests, no code coverage (PHPUnit 10+)
if: ${{ matrix.coverage == false && startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
run: composer test10

- name: Run the unit tests with code coverage (PHPUnit < 10)
if: ${{ matrix.coverage == true && ! startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
- name: Run the unit tests with code coverage
if: ${{ matrix.coverage == true }}
run: composer coverage -- --coverage-clover clover.xml

- name: Run the unit tests with code coverage (PHPUnit 10+)
if: ${{ matrix.coverage == true && startsWith( steps.phpunit_version.outputs.VERSION, '10.' ) }}
run: composer coverage10 -- --coverage-clover clover.xml

- name: Stop proxy server
continue-on-error: true
run: |
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ certificates/etag-*.txt
# Ignore temporary files generated by the testing proxy.
tests/utils/proxy/__pycache__
tests/utils/proxy/*.pid
tests/utils/pids
42 changes: 31 additions & 11 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,25 +87,45 @@
"@php ./vendor/squizlabs/php_codesniffer/bin/phpcbf"
],
"test": [
"@php ./vendor/phpunit/phpunit/phpunit --no-coverage"
],
"test10": [
"@php ./vendor/phpunit/phpunit/phpunit -c phpunit10.xml.dist --no-coverage"
"./scripts/run-phpunit.sh --no-coverage"
],
"coverage": [
"@php ./vendor/phpunit/phpunit/phpunit"
"./scripts/run-phpunit.sh"
],
"testserver:start": [
"./scripts/start-test-environment.sh"
],
"testserver:stop": [
"./scripts/stop-test-environment.sh"
],
"test:withserver": [
"@putenv REQUESTS_HTTP_PROXY=localhost:9002",
"@putenv REQUESTS_HTTP_PROXY_AUTH=localhost:9003",
"@putenv REQUESTS_HTTP_PROXY_AUTH_USER=test",
"@putenv REQUESTS_HTTP_PROXY_AUTH_PASS=pass",
Comment on lines +102 to +105
Copy link
Member

Choose a reason for hiding this comment

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

Could these be moved to a separate Composer script which is @ referenced here ? (to avoid the duplication in the coverage:withserver script)

"@testserver:start",
"@test",
"@testserver:stop"
],
"coverage10": [
"@php ./vendor/phpunit/phpunit/phpunit -c phpunit10.xml.dist"
"coverage:withserver": [
"@putenv REQUESTS_HTTP_PROXY=localhost:9002",
"@putenv REQUESTS_HTTP_PROXY_AUTH=localhost:9003",
"@putenv REQUESTS_HTTP_PROXY_AUTH_USER=test",
"@putenv REQUESTS_HTTP_PROXY_AUTH_PASS=pass",
"@testserver:start",
"@coverage",
"@testserver:stop"
]
},
"scripts-descriptions": {
"lint": "Lint PHP files to find parse errors.",
"checkcs": "Check the entire codebase for code-style issues.",
"fixcs": "Fix all auto-fixable code-style issues in the entire codebase.",
"test": "Run the unit tests on PHPUnit 5.x - 9.x without code coverage.",
"test10": "Run the unit tests on PHPUnit 10.x without code coverage.",
"coverage": "Run the unit tests on PHPUnit 5.x - 9.x with code coverage.",
"coverage10": "Run the unit tests on PHPUnit 10.x with code coverage."
"test": "Run the unit tests without code coverage (auto-detects PHPUnit version)",
"coverage": "Run the unit tests with code coverage (auto-detects PHPUnit version)",
"testserver:start": "Start the test environment including test server and proxy servers (Note: environment variables will only be available in a sourced shell)",
"testserver:stop": "Stop all running test environment servers",
"test:withserver": "Start test servers, run PHPUnit tests with appropriate config, then stop servers",
"coverage:withserver": "Start test servers, run PHPUnit tests with code coverage, then stop servers"
}
}
20 changes: 20 additions & 0 deletions scripts/run-phpunit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/sh


# Set up PHPUnit command
# We're using composer exec to ensure we use the version of PHP that Composer
# is locked into, instead of the version of PHP that the system provides.
PHPUNIT="composer exec phpunit --"

# Detect PHPUnit version
PHPUNIT_VERSION=$($PHPUNIT --version | grep -oE '[0-9]+\.[0-9]+' | head -n 1)

# Determine config file based on version
if printf '%s\n%s\n' "10.0" "$PHPUNIT_VERSION" | sort -V -C 2>/dev/null; then
CONFIG_FILE="phpunit10.xml.dist"
else
CONFIG_FILE="phpunit.xml.dist"
fi

# Run the tests
$PHPUNIT -c "$CONFIG_FILE" "$@"
125 changes: 125 additions & 0 deletions scripts/start-test-environment.sh
schlessera marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/bin/sh

# Try to determine script location
if [ -n "${BASH_SOURCE:-}" ]; then
# Bash-specific path resolution
# Shellcheck complains about POSIX arrays being unreferenced, but this bit
# conditionally run on Bash only.
# shellcheck disable=SC3054
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
else
# POSIX fallback - assume we're in the repository root
PROJECT_ROOT="$(pwd)"
SCRIPT_DIR="$PROJECT_ROOT/scripts"
fi

# Detect if we're being sourced (POSIX-compatible way)
sourced=0
if [ -n "$ZSH_EVAL_CONTEXT" ]; then
case $ZSH_EVAL_CONTEXT in *:file:*) sourced=1;; esac
elif [ -n "$KSH_VERSION" ]; then
[ "$(cd $(dirname -- "$0") && pwd -P)/$(basename -- "$0")" != "$(cd $(dirname -- "${.sh.file}") && pwd -P)/$(basename -- "${.sh.file}")" ] && sourced=1
elif [ -n "$BASH_VERSION" ]; then
(return 0 2>/dev/null) && sourced=1
else
# POSIX fallback - check if we can modify our environment
# Try to modify a test variable
TEST_VAR="test"
if [ -z "${TEST_VAR:-}" ]; then
sourced=0
else
sourced=1
fi
fi

if [ $sourced -eq 0 ]; then
echo "Warning: This script should be sourced to set environment variables"
echo "Please either:"
echo "1. Source this script: source scripts/start-test-environment.sh"
echo "2. Or manually set these environment variables:"
echo " export REQUESTS_TEST_HOST_HTTP=localhost:8080"
echo " export REQUESTS_HTTP_PROXY=localhost:9002"
echo " export REQUESTS_HTTP_PROXY_AUTH=localhost:9003"
echo " export REQUESTS_HTTP_PROXY_AUTH_USER=test"
echo " export REQUESTS_HTTP_PROXY_AUTH_PASS=pass"
if [ -n "${BASH_VERSION:-}" ]; then
exit 1
fi
fi

PID_DIR="${PROJECT_ROOT}/tests/utils/pids"

# Check if mitmproxy is installed
if ! command -v mitmdump >/dev/null 2>&1; then
echo "Error: mitmproxy is not installed. Please install it with: pip3 install mitmproxy"
schlessera marked this conversation as resolved.
Show resolved Hide resolved
return 1 2>/dev/null || exit 1
fi

# Get mitmproxy version and compare with minimum required
MITM_VERSION=$(mitmdump --version | grep -oE '[0-9]+\.[0-9]+\.[0-9]+' | head -n1)
MINIMUM_VERSION="11.0.2"

# POSIX-compatible version comparison
if ! printf '%s\n%s\n' "$MINIMUM_VERSION" "$MITM_VERSION" | sort -V -C 2>/dev/null; then
echo "Error: mitmproxy version $MITM_VERSION is too old"
echo "Please upgrade to version $MINIMUM_VERSION or newer with: pip3 install --upgrade mitmproxy"
return 1 2>/dev/null || exit 1
fi

echo "Found mitmproxy version $MITM_VERSION"

# Create directory for PID files if it doesn't exist
mkdir -p "$PID_DIR"

# Start the test server
echo "Starting test server..."
PORT=8080 "${PROJECT_ROOT}/vendor/bin/start.sh"
echo $! > "${PID_DIR}/test-server.pid"
REQUESTS_TEST_HOST_HTTP="localhost:8080"
export REQUESTS_TEST_HOST_HTTP

# Start proxy servers
echo "Starting proxy servers..."
PORT=9002 "${PROJECT_ROOT}/tests/utils/proxy/start.sh"
echo $! > "${PID_DIR}/proxy-server.pid"

PORT=9003 AUTH="test:pass" "${PROJECT_ROOT}/tests/utils/proxy/start.sh"
echo $! > "${PID_DIR}/proxy-auth-server.pid"

# Set environment variables
REQUESTS_HTTP_PROXY="localhost:9002"
REQUESTS_HTTP_PROXY_AUTH="localhost:9003"
REQUESTS_HTTP_PROXY_AUTH_USER="test"
REQUESTS_HTTP_PROXY_AUTH_PASS="pass"
Comment on lines +90 to +94
Copy link
Member

Choose a reason for hiding this comment

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

Considering the changes to the Composer script to use @putenv (in commit fb62d2b), so this be read out from env if available ?


export REQUESTS_HTTP_PROXY
export REQUESTS_HTTP_PROXY_AUTH
export REQUESTS_HTTP_PROXY_AUTH_USER
export REQUESTS_HTTP_PROXY_AUTH_PASS

# Wait for servers to be ready
echo "Waiting for servers to be ready..."
sleep 2

# Test server connections
echo "Testing server connections..."
if ! curl -s -I http://localhost:8080 >/dev/null 2>&1; then
echo "Test server not responding"
return 1 2>/dev/null || exit 1
fi

if ! curl -s -I http://localhost:9002 >/dev/null 2>&1; then
echo "Proxy server not responding"
return 1 2>/dev/null || exit 1
fi

echo "Test environment is ready!"
echo "Environment variables set:"
echo "REQUESTS_TEST_HOST_HTTP=localhost:8080"
echo "REQUESTS_HTTP_PROXY=localhost:9002"
echo "REQUESTS_HTTP_PROXY_AUTH=localhost:9003"
echo "REQUESTS_HTTP_PROXY_AUTH_USER=test"
echo "REQUESTS_HTTP_PROXY_AUTH_PASS=pass"
Comment on lines +119 to +123
Copy link
Member

Choose a reason for hiding this comment

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

Should this be using the variables instead of having the values hard-coded in the echo ?


return 0 2>/dev/null || exit 0
Loading