From 2bea803b9fd4c3c040b514c54f1784b9bc4c3a61 Mon Sep 17 00:00:00 2001 From: Liam Griffin-Jowett Date: Wed, 15 Apr 2026 00:04:34 +0100 Subject: [PATCH] add 'terraform test' command --- lib/ruby_terraform.rb | 50 ++++++++++++++ lib/ruby_terraform/commands.rb | 1 + lib/ruby_terraform/commands/test.rb | 83 +++++++++++++++++++++++ lib/ruby_terraform/options/definitions.rb | 5 +- spec/ruby_terraform/commands/test_spec.rb | 65 ++++++++++++++++++ 5 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 lib/ruby_terraform/commands/test.rb create mode 100644 spec/ruby_terraform/commands/test_spec.rb diff --git a/lib/ruby_terraform.rb b/lib/ruby_terraform.rb index 089dd3e9..7ee4ac20 100644 --- a/lib/ruby_terraform.rb +++ b/lib/ruby_terraform.rb @@ -1316,6 +1316,56 @@ def taint(parameters = {}, invocation_options = {}) parameters, invocation_options) end + # Invokes the +terraform test+ command which executes integration tests + # defined in +.tftest.hcl+ files. + # + # Terraform discovers test files in the configured test directory (by + # default +tests+) and in the root module, then runs each +run+ block in + # turn, reporting on the outcome of the assertions. + # + # @param parameters The parameters used to invoke the command + # @option parameters [String] :chdir The path of a working directory to + # switch to before executing the given subcommand. + # @option parameters [String] :cloud_run If set, executes the tests + # remotely using the given Terraform Cloud/Enterprise module source + # address rather than running them locally. + # @option parameters [String] :filter Restrict which test files are + # executed; if both +:filter+ and +:filters+ are provided, all filters + # will be passed to terraform. + # @option parameters [Array] :filters An array of test file paths + # to restrict which test files are executed; if both +:filter+ and + # +:filters+ are provided, all filters will be passed to terraform. + # @option parameters [Boolean] :json (false) Whether or not to produce + # output in a machine-readable JSON format. + # @option parameters [Boolean] :no_color (false) Whether or not the output + # from the command should be in color. + # @option parameters [String] :test_directory The directory containing + # test files; defaults to +"tests"+. + # @option parameters [Hash] :vars A map of variables to + # be passed to the terraform configuration. + # @option parameters [String] :var_file The path to a terraform var file; + # if both +:var_file+ and +:var_files+ are provided, all var files will + # be passed to terraform. + # @option parameters [Array] :var_files An array of paths to + # terraform var files; if both +:var_file+ and +:var_files+ are + # provided, all var files will be passed to terraform. + # @option parameters [Boolean] :verbose (false) When +true+, prints the + # plan or state for each test run block as it executes. + # @param [Hash] invocation_options Additional options + # controlling the invocation of the command. + # @option invocation_options [Hash] :environment A map + # of environment variables to expose at command invocation time. + # + # @example Basic Invocation + # RubyTerraform.test( + # filters: ['tests/network.tftest.hcl'], + # verbose: true) + # + def test(parameters = {}, invocation_options = {}) + exec(RubyTerraform::Commands::Test, + parameters, invocation_options) + end + # Invokes the +terraform untaint+ command which removes the 'tainted' state # from a resource instance. # diff --git a/lib/ruby_terraform/commands.rb b/lib/ruby_terraform/commands.rb index 23780033..9f92c366 100644 --- a/lib/ruby_terraform/commands.rb +++ b/lib/ruby_terraform/commands.rb @@ -26,6 +26,7 @@ require_relative 'commands/state_remove' require_relative 'commands/state_show' require_relative 'commands/taint' +require_relative 'commands/test' require_relative 'commands/untaint' require_relative 'commands/validate' require_relative 'commands/workspace_delete' diff --git a/lib/ruby_terraform/commands/test.rb b/lib/ruby_terraform/commands/test.rb new file mode 100644 index 00000000..513af3af --- /dev/null +++ b/lib/ruby_terraform/commands/test.rb @@ -0,0 +1,83 @@ +# frozen_string_literal: true + +require_relative 'base' +require_relative '../options/global' + +module RubyTerraform + module Commands + # Wraps the +terraform test+ command which executes automated integration + # tests defined in +.tftest.hcl+ files. + # + # Terraform discovers test files in the configured test directory (by + # default +tests+) and in the root module, then runs each +run+ block in + # turn, reporting on the outcome of the assertions. + # + # For options accepted on construction, see {#initialize}. + # + # When executing an instance of {Test} via {#execute}, the following + # options are supported: + # + # * +:chdir+: the path of a working directory to switch to before executing + # the given subcommand. + # * +:cloud_run+: if set, executes the tests remotely using the given + # Terraform Cloud/Enterprise module source address rather than running + # them locally. + # * +:filter+: restrict which test files are executed; if both +:filter+ + # and +:filters+ are provided, all filters will be passed to terraform. + # * +:filters+: an array of test file paths to restrict which test files + # are executed; if both +:filter+ and +:filters+ are provided, all + # filters will be passed to terraform. + # * +:json+: whether or not to produce output in a machine-readable JSON + # format; defaults to +false+. + # * +:no_color+: whether or not the output from the command should be in + # color; defaults to +false+. + # * +:test_directory+: the directory containing test files; defaults to + # +"tests"+. + # * +:vars+: a map of variables to be passed to the terraform configuration. + # * +:var_file+: the path to a terraform var file; if both +:var_file+ and + # +:var_files+ are provided, all var files will be passed to terraform. + # * +:var_files+: an array of paths to terraform var files; if both + # +:var_file+ and +:var_files+ are provided, all var files will be passed + # to terraform. + # * +:verbose+: when +true+, print the plan or state for each test run + # block as it executes; defaults to +false+. + # + # The {#execute} method accepts an optional second parameter which is a map + # of invocation options. Currently, the only supported option is + # +:environment+ which is a map of environment variables to expose during + # invocation of the command. + # + # @example Basic Invocation + # RubyTerraform::Commands::Test.new.execute( + # filters: ['tests/network.tftest.hcl'], + # verbose: true) + # + class Test < Base + include RubyTerraform::Options::Global + + # @!visibility private + def subcommands + %w[test] + end + + # @!visibility private + def options + %w[ + -cloud-run + -filter + -json + -no-color + -test-directory + -var + -var-file + -verbose + ] + super + end + + # @!visibility private + def parameter_defaults(_parameters) + { vars: {}, var_files: [], filters: [] } + end + end + end +end diff --git a/lib/ruby_terraform/options/definitions.rb b/lib/ruby_terraform/options/definitions.rb index 30c88bab..0ab7d686 100644 --- a/lib/ruby_terraform/options/definitions.rb +++ b/lib/ruby_terraform/options/definitions.rb @@ -22,7 +22,7 @@ module Options end, # string repeatable options - %w[-var-file -target -platform -plugin-dir -replace].map do |o| + %w[-var-file -target -platform -plugin-dir -replace -filter].map do |o| definition( name: o, option_type: :standard, value_type: :string, repeatable: true @@ -68,6 +68,7 @@ module Options -reconfigure -recursive -update + -verbose ].map do |o| definition(name: o, option_type: :flag, value_type: :boolean) end, @@ -76,6 +77,7 @@ module Options %w[ -backup -backup-out + -cloud-run -from-module -fs-mirror -id @@ -88,6 +90,7 @@ module Options -provider -state -state-out + -test-directory -type ].map do |o| definition(name: o, option_type: :standard, value_type: :string) diff --git a/spec/ruby_terraform/commands/test_spec.rb b/spec/ruby_terraform/commands/test_spec.rb new file mode 100644 index 00000000..1f3d83c5 --- /dev/null +++ b/spec/ruby_terraform/commands/test_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe RubyTerraform::Commands::Test do + before do + RubyTerraform.configure do |config| + config.binary = 'path/to/binary' + end + end + + after do + RubyTerraform.reset! + end + + it_behaves_like( + 'a command without a binary supplied', + described_class, 'test' + ) + + it_behaves_like( + 'a command with a flag', + described_class, 'test', :json + ) + + it_behaves_like( + 'a command with a flag', + described_class, 'test', :no_color + ) + + it_behaves_like( + 'a command with a flag', + described_class, 'test', :verbose + ) + + it_behaves_like( + 'a command with an option', + described_class, 'test', :cloud_run + ) + + it_behaves_like( + 'a command with an option', + described_class, 'test', :test_directory + ) + + it_behaves_like( + 'a command with an array option', + described_class, 'test', :filters + ) + + it_behaves_like( + 'a command that accepts vars', + described_class, 'test' + ) + + it_behaves_like( + 'a command with an array option', + described_class, 'test', :var_files + ) + + it_behaves_like( + 'a command with global options', + described_class, 'test' + ) +end