This directory contains the BATS (Bash Automated Testing System) test suite for phpvm.
tests/
├── README.md # This file
├── test_helper.bash # Setup, teardown, and helper functions
├── 01_core.bats # Core functionality tests
├── 02_features.bats # Feature and placeholder tests
└── 03_error_handling.bats # Error handling and edge case tests
# From project root
make test-bats
# Or directly with BATS
bats tests/bats tests/01_core.batsbats -t tests/bats -t tests/ | tee test-results.tap#!/usr/bin/env bats
load test_helper
@test "description of what you're testing" {
# Arrange - Setup test conditions
local test_input="8.1"
# Act - Execute the code
run command_to_test "$test_input"
# Assert - Verify results
[ "$status" -eq 0 ]
[ "$output" = "expected output" ]
}The test_helper.bash file provides:
setup()- Runs before each testteardown()- Runs after each testcreate_mock_php()- Helper to create mock PHP installations- Environment variables for testing
- Use descriptive names that explain what is being tested
- Start with the command or function name
- Describe the expected behavior
- Example:
phpvm current shows no active version initially
# Test command execution
@test "command succeeds" {
run bash "$BATS_TEST_DIRNAME/../phpvm.sh" command arg
[ "$status" -eq 0 ]
}
# Test command output
@test "command outputs expected text" {
run bash "$BATS_TEST_DIRNAME/../phpvm.sh" command
[[ "$output" =~ "expected text" ]]
}
# Test command failure
@test "command fails with invalid input" {
run bash "$BATS_TEST_DIRNAME/../phpvm.sh" command invalid
[ "$status" -ne 0 ]
}# Test internal function
@test "function returns correct value" {
run function_name arg1 arg2
[ "$status" -eq 0 ]
[ "$output" = "expected" ]
}Tests for fundamental functionality:
- Version validation
- Input sanitization
- Directory operations
- File operations
- Version resolution
- Help and version commands
Tests for features (including placeholders):
- exec, run commands
- ls-remote command
- alias management
- cache management
- Help text content
Tests for error conditions:
- Missing arguments
- Invalid input
- Edge cases
- Security validation
- Graceful degradation
- Test one thing at a time - Each test should verify a single behavior
- Use setup/teardown - Keep tests independent
- Make tests readable - Clear names and comments
- Test error cases - Don't just test happy paths
- Use helpers - Reduce duplication
- Keep tests fast - Use mocks when possible
bats tests/01_core.bats -f "test name pattern"@test "debug test" {
run command
echo "Status: $status" >&3
echo "Output: $output" >&3
[ "$status" -eq 0 ]
}bats -t tests/run command
[ "$status" -eq 0 ] # Success
[ "$status" -eq 1 ] # General error
[ "$status" -eq 2 ] # Invalid argument
[ "$status" -ne 0 ] # Any errorrun command
[ "$output" = "exact match" ]
[[ "$output" =~ "pattern" ]]
[[ "$output" =~ ^prefix ]][ -f "$file" ] # File exists
[ -d "$dir" ] # Directory exists
[ -x "$file" ] # File is executable
[ ! -f "$file" ] # File doesn't existWhen adding new functionality:
- Create test first (TDD approach)
- Add test to appropriate file
- Run test to see it fail
- Implement feature
- Run test to see it pass
- Refactor if needed
These tests run automatically in GitHub Actions on:
- Every push to main/development branches
- Every pull request
- Weekly scheduled runs
See .github/workflows/quality.yml for CI configuration.
Test Coverage: 50+ test cases Last Updated: January 15, 2026