Back to Repositories

Testing Container Lifecycle Management in Kamal

This integration test suite validates the lifecycle management of accessory containers in Kamal, focusing on core operations like booting, stopping, starting, restarting, logging, and removal. The tests ensure reliable container orchestration and state management.

Test Coverage Overview

The test suite provides comprehensive coverage of accessory container lifecycle operations in Kamal.

Key areas tested include:
  • Container initialization and boot sequence
  • State transitions between running and stopped states
  • Container restart functionality
  • Log output verification
  • Clean removal of containers
Integration points focus on container registry interaction and Docker command execution.

Implementation Analysis

The testing approach uses Minitest’s integration framework to validate container management operations sequentially. The implementation follows a clear pattern of action-assertion pairs, utilizing helper methods for state verification.

Technical patterns include:
  • Command execution through the kamal helper method
  • Custom assertions for container state verification
  • Captured output analysis for logs and details
  • Regular expression matching for state validation

Technical Details

Testing tools and configuration:
  • Minitest as the testing framework
  • Integration with Docker container runtime
  • Custom helper methods for container state inspection
  • Regular expressions for output validation
  • Busybox container as the test subject
  • Local registry setup on port 4443

Best Practices Demonstrated

The test suite exemplifies several testing best practices for container management validation.

Notable practices include:
  • Isolated test scenarios with clear setup and teardown
  • Comprehensive lifecycle testing
  • Reusable helper methods for common assertions
  • Explicit state verification after each operation
  • Clean resource management with container removal

basecamp/kamal

test/integration/accessory_test.rb

            
require_relative "integration_test"

class AccessoryTest < IntegrationTest
  test "boot, stop, start, restart, logs, remove" do
    kamal :accessory, :boot, :busybox
    assert_accessory_running :busybox

    kamal :accessory, :stop, :busybox
    assert_accessory_not_running :busybox

    kamal :accessory, :start, :busybox
    assert_accessory_running :busybox

    kamal :accessory, :restart, :busybox
    assert_accessory_running :busybox

    logs = kamal :accessory, :logs, :busybox, capture: true
    assert_match /Starting busybox.../, logs

    kamal :accessory, :remove, :busybox, "-y"
    assert_accessory_not_running :busybox
  end

  private
    def assert_accessory_running(name)
      assert_match /registry:4443\/busybox:1.36.0   "sh -c 'echo \\"Start/, accessory_details(name)
    end

    def assert_accessory_not_running(name)
      assert_no_match /registry:4443\/busybox:1.36.0   "sh -c 'echo \\"Start/, accessory_details(name)
    end

    def accessory_details(name)
      kamal :accessory, :details, name, capture: true
    end
end