Thank you for your interest in contributing to czruby! This guide will help you set up your development environment and run tests.
- Setting Up Development Environment
- Running Tests
- Writing Tests
- Debugging Test Failures
- CI/CD Integration
- Common Issues
You can develop and test czruby either natively on your machine or using containers. Containers provide a consistent environment and are recommended for most contributors.
If you prefer to run tests natively, you'll need the following dependencies:
-
Z-Shell (zsh) version 5.x or later
# macOS (comes pre-installed) zsh --version # Linux (Ubuntu/Debian) sudo apt-get install zsh # Linux (Fedora) sudo dnf install zsh
-
Ruby (any version)
# macOS (comes pre-installed) ruby --version # Linux (Ubuntu/Debian) sudo apt-get install ruby # Linux (Fedora) sudo dnf install ruby
-
GNU Coreutils (for
realpath/grealpath)# macOS (via Homebrew) brew install coreutils # macOS (via MacPorts) sudo port install coreutils # Linux - already included
Set the required XDG environment variables in your shell configuration:
export XDG_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
export XDG_CACHE_HOME="${XDG_CACHE_HOME:-$HOME/.cache}"
export XDG_CONFIG_HOME="${XDG_CONFIG_HOME:-$HOME/.config}"Containers provide a consistent, isolated testing environment without requiring native dependencies.
Install either Docker or Podman:
Docker:
- macOS: Docker Desktop for Mac
- Linux: Docker Engine
- Windows: Docker Desktop for Windows
Podman:
- macOS:
brew install podman - Linux: Podman Installation Guide
No additional configuration is required. The container scripts auto-detect which runtime is available.
Containers provide the fastest and most reliable way to run tests, matching the CI environment exactly.
# Run all tests
./scripts/test-container.sh
# Run specific test file
./scripts/test-container.sh test/test_czruby_setup.zsh
# Force rebuild and run tests
./scripts/test-container.sh --build# Run all tests
docker compose up test
# Run specific test
docker compose run --rm test zsh test/test_czruby_setup.zsh
# Interactive shell for debugging
docker compose run --rm shell# Build image
docker build -t czruby-test .
# Run all tests
docker run --rm czruby-test
# Run specific test
docker run --rm czruby-test zsh test/test_czruby_setup.zsh
# Interactive shell
docker run --rm -it czruby-test zsh
# With live code mounting
docker run --rm -v $(pwd):/app czruby-testIf you have the native dependencies installed:
# Run all tests
zsh test/run_all_tests.zsh
# Run specific test suite
zsh test/test_czruby_setup.zsh
zsh test/test_czruby_use.zsh
zsh test/test_integration.zsh# Check zsh syntax for all functions
for file in fn/*; do zsh -n "$file"; done
zsh -n czruby.plugin.conf# Run ShellCheck (with zsh-appropriate exclusions)
shellcheck --shell=bash --severity=warning \
-e SC2034 -e SC2128 -e SC2154 -e SC2206 \
-e SC2296 -e SC2299 -e SC1090 -e SC2086 \
fn/* czruby.plugin.confczruby uses a custom zsh testing framework located in test/test_helper.zsh.
Each test file should follow this structure:
#!/usr/bin/env zsh
# Source the test helper
source "$(dirname "$0")/test_helper.zsh"
# Define test functions
test_example_functionality() {
# Setup
local expected="some value"
# Execute
local actual=$(some_function)
# Assert
assert_equals "$expected" "$actual" "Function should return expected value"
}
test_another_feature() {
# Your test code here
assert_success some_command
}
# Run all tests
run_test test_example_functionality
run_test test_another_feature
# Print summary
print_summaryThe test framework provides these assertion functions:
assert_equals <expected> <actual> [message]- Values must be equalassert_not_equals <value1> <value2> [message]- Values must differassert_contains <haystack> <needle> [message]- String contains substringassert_not_contains <haystack> <needle> [message]- String doesn't contain substringassert_file_exists <path> [message]- File must existassert_file_not_exists <path> [message]- File must not existassert_dir_exists <path> [message]- Directory must existassert_symlink <path> <target> [message]- Symlink must point to targetassert_array_contains <array_name> <value> [message]- Array contains valueassert_array_not_contains <array_name> <value> [message]- Array doesn't contain valueassert_success <command> [message]- Command exits with 0assert_failure <command> [message]- Command exits with non-zeroassert_empty <value> [message]- Value is emptyassert_not_empty <value> [message]- Value is not empty
Use the helper functions to create mock Ruby installations:
test_with_mock_ruby() {
# Create mock Ruby in test directory
local ruby_dir=$(create_mock_ruby "3.2.0")
# Use in tests
assert_dir_exists "$ruby_dir/bin"
assert_file_exists "$ruby_dir/bin/ruby"
}
test_with_system_ruby() {
# Create mock system Ruby
create_system_ruby "2.7.0"
# Test system Ruby detection
assert_file_exists "/usr/bin/ruby"
}The easiest way to debug test failures is using the interactive shell:
# Start interactive shell with live code mounting
./scripts/test-shell.shInside the shell, you can:
# Run individual test files
zsh test/test_czruby_setup.zsh
# Source czruby manually
source czruby.plugin.conf
autoload -Uz czruby czruby_setup czruby_use
# Test functions interactively
czruby --version
czruby_setup
echo $rubies
# Run specific test functions
source test/test_helper.zsh
setup_test_env
test_czruby_version # Replace with actual test function name- Check test output - Tests print detailed failure messages
- Inspect environment - Use
echostatements to verify variable values - Run tests in isolation - Test individual files to narrow down issues
- Use zsh debugging - Add
set -xto enable trace mode - Check file permissions - Ensure test scripts are executable
# Check if functions are loaded
autoload -Uz czruby && whence -v czruby
# Inspect arrays
echo $rubies
echo $path
# Check XDG directories
ls -la $XDG_DATA_HOME/czruby/
# View generated Ruby configs
cat $XDG_DATA_HOME/czruby/systemThe container-based tests can be integrated into any CI/CD system.
Already configured in .github/workflows/test.yml.
test:
image: ubuntu:22.04
before_script:
- apt-get update && apt-get install -y docker.io
script:
- ./scripts/test-container.shpipeline {
agent any
stages {
stage('Test') {
steps {
sh './scripts/test-container.sh'
}
}
}
}version: 2.1
jobs:
test:
docker:
- image: cimg/base:stable
steps:
- checkout
- setup_remote_docker
- run: ./scripts/test-container.shAdd to .git/hooks/pre-commit:
#!/bin/bash
./scripts/test-container.sh
exit $?Error: Error: Neither Docker nor Podman is installed.
Solution: Install Docker or Podman (see Container Setup)
Error: Permission denied: ./scripts/test-container.sh
Solution:
chmod +x scripts/*.shCause: Different environments (native vs container)
Solution: Always test using containers before pushing:
./scripts/test-container.sh --buildError: grealpath: command not found
Solution: Install GNU coreutils:
brew install coreutilsError: Tests fail with missing directory errors
Solution: Export XDG variables:
export XDG_DATA_HOME="$HOME/.local/share"
export XDG_CACHE_HOME="$HOME/.cache"
export XDG_CONFIG_HOME="$HOME/.config"Error: Docker build errors
Solution:
- Check your internet connection
- Try rebuilding:
./scripts/test-container.sh --build - Clear Docker cache:
docker system prune -a
Solution:
- Use containers (faster than native on some systems)
- Run specific test files instead of full suite
- Use Docker layer caching (automatic)
If you encounter issues not covered here:
- Check existing GitHub Issues
- Review test output carefully - it's usually descriptive
- Try the interactive shell for debugging
- Open a new issue with:
- Your operating system and version
- Docker/Podman version (if using containers)
- Complete error output
- Steps to reproduce
- Follow existing code conventions
- Use zsh best practices (autoload, no global variables)
- Add tests for new features
- Update documentation for significant changes
- Keep functions focused and single-purpose
- Fork the repository
- Create a feature branch
- Make your changes
- Ensure all tests pass:
./scripts/test-container.sh - Update documentation if needed
- Submit a pull request with a clear description
Thank you for contributing to czruby!