Testcontainers for Ruby

repository·main·Indexed 41 days ago

https://github.com/testcontainers/testcontainers-ruby

A Ruby library for running Docker containers during tests to ensure consistent and isolated environments. It provides a generic DockerContainer class and specialized modules for common services including PostgresContainer, MysqlContainer, MariadbContainer, RedisContainer, RedpandaContainer, MongoContainer, ElasticsearchContainer, NginxContainer, RabbitmqContainer, SeleniumContainer, and ComposeContainer.

Tokens
19.8K
Snippets
81
Records
92
Agent score
51%

What's inside Testcontainers Ruby

  1. Use shared container networks

    main

    To allow multiple containers to communicate with each other, attach them to a shared network using Testcontainers::Network::SHARED (or Testcontainers::Network.shared). This singleton network persists for the lifetime of your test suite and is cleaned up automatically when the process exits.

    network = Testcontainers::Network::SHARED
    
    redis = Testcontainers::DockerContainer.new("redis:6.2-alpine").with_network(network)
    nginx = Testcontainers::DockerContainer.new("nginx:alpine").with_network(network)
  2. Use specialized modules for common services

    main

    Instead of using the generic DockerContainer, Testcontainers provides specialized modules for common databases and services. These modules offer pre-configured setups and reduce boilerplate code.

    Available modules include:

    • ComposeContainer
    • ElasticsearchContainer
    • MariadbContainer
    • MongoContainer
    • MysqlContainer
    • NginxContainer
    • PostgresContainer
    • RabbitmqContainer
    • RedisContainer
    • RedpandaContainer
    • SeleniumContainer
  3. Use Redpanda with RSpec

    main

    To avoid the overhead of starting/stopping containers for every single test, manage the Redpanda container lifecycle within RSpec's before(:suite) and after(:suite) blocks. This allows you to attach the container instance to the RSpec configuration for easy access in your specs.

    RSpec.configure do |config|
      # Register a setting to hold the container instance
      config.add_setting :redpanda_container, default: nil
    
      config.before(:suite) do
        # Start the container once before the entire test suite runs
        config.redpanda_container = Testcontainers::RedpandaContainer.new.start
      end
    
      config.after(:suite) do
        # Clean up the container after the suite finishes
        config.redpanda_container&.stop
        config.redpanda_container&.remove
      end
    end
  4. Connect to a running container

    main

    To connect your application code to a container, use @container.host to get the host address and @container.mapped_port(original_port) to get the dynamically assigned port on the host. It is recommended to use @container.wait_for_tcp_port(port) to ensure the service is ready before attempting a connection.

    @redis_container = Testcontainers::DockerContainer.new("redis:6.2-alpine").with_exposed_ports(6379)
    @redis_container.start
    @redis_container.wait_for_tcp_port(6379)
    
    host = @redis_container.host
    port = @redis_container.mapped_port(6379)
    
    # Use host and port to initialize your application component
    @under_test = RedisBackedCache.new(host, port)
  5. Develop with testcontainers-ruby

    main

    To set up a local development environment for this repository:

    1. Run bin/setup to install dependencies.
    2. Run rake test to execute the test suite.
    3. Use bin/console for an interactive prompt to experiment with the API.
    4. To install the gem locally from the source, run bundle exec rake install.
  6. Integrate MariaDB with RSpec

    main

    To avoid using global variables, you can attach the container to the RSpec configuration. Use before(:suite) to start the container and after(:suite) to stop and remove it. You can also inject the database_url into the ENV for your application to consume.

    RSpec.configure do |config|
      # Add a setting to access the container via RSpec configuration
      config.add_setting :mariadb_container, default: nil
    
      config.before(:suite) do
        # Start the container and assign it to the config setting
        config.mariadb_container = Testcontainers::MariadbContainer.new.start
        
        # Expose the connection via DATABASE_URL
        ENV["DATABASE_URL"] = config.mariadb_container.database_url(protocol: "mysql2")
      end
    
      config.after(:suite) do
        # Clean up the container
        config.mariadb_container&.stop
        config.mariadb_container&.remove
      end
    end
  7. Start a Docker container for your tests

    main

    You can manage container lifecycles using Testcontainers::DockerContainer. Use .new(image_name) to specify the image and .with_exposed_ports(port) to expose specific ports. Call .start to launch the container and .stop to shut it down.

    require "testcontainers"
    
    # Create and start a container
    @redis_container = Testcontainers::DockerContainer.new("redis:6.2-alpine").with_exposed_ports(6379)
    @redis_container.start
    
    # Stop the container
    @redis_container.stop if @redis_container
  8. Install the testcontainers gem

    main

    You can install the testcontainers gem using Bundler or by using the gem command directly.

    If you are using Bundler, add it to your Gemfile by running:

    $ bundle add testcontainers

    If you are not using Bundler, install it via:

    $ gem install testcontainers
    $ bundle add testcontainers
  9. Install testcontainers-postgres

    main

    To use the Postgres module, add testcontainers-postgres to your application's Gemfile within the :test group and run bundle install.

    Alternatively, you can install the gem directly using gem install.

    group :test do
      gem "testcontainers-postgres"
    end
    $ bundle install
    # or
    $ gem install testcontainers-postgres
  10. Use generic Docker containers with Testcontainers

    main

    You can manage arbitrary Docker containers using Testcontainers::DockerContainer. This involves initializing the container with an image, exposing ports, starting the container, and then retrieving connection details.

    Lifecycle and Connection

    1. Initialize: Use Testcontainers::DockerContainer.new("image:tag").
    2. Configure: Use .with_exposed_port(port) to expose container ports.
    3. Start: Call .start to launch the container.
    4. Connect: Use .host and .mapped_port(container_port) to find where the service is running on your host machine.
    5. Cleanup: Call .stop and .delete to remove the container after tests.
    container = Testcontainers::DockerContainer.new("redis:6.2-alpine").with_exposed_port(6379)
    container.start
    
    # Access connection details
    host = container.host
    port = container.mapped_port(6379)
    
    # Cleanup
    container.stop
    container.delete