use crate::Terraform;
use crate::command::TerraformCommand;
use crate::error::Result;
use crate::exec::{self, CommandOutput};
#[derive(Debug, Clone, Default)]
pub struct TestCommand {
filter: Option<String>,
json: bool,
test_directory: Option<String>,
verbose: bool,
vars: Vec<(String, String)>,
var_files: Vec<String>,
parallelism: Option<u32>,
junit_xml: Option<String>,
raw_args: Vec<String>,
}
impl TestCommand {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn filter(mut self, name: &str) -> Self {
self.filter = Some(name.to_string());
self
}
#[must_use]
pub fn json(mut self) -> Self {
self.json = true;
self
}
#[must_use]
pub fn test_directory(mut self, path: &str) -> Self {
self.test_directory = Some(path.to_string());
self
}
#[must_use]
pub fn verbose(mut self) -> Self {
self.verbose = true;
self
}
#[must_use]
pub fn var(mut self, name: &str, value: &str) -> Self {
self.vars.push((name.to_string(), value.to_string()));
self
}
#[must_use]
pub fn var_file(mut self, path: &str) -> Self {
self.var_files.push(path.to_string());
self
}
#[must_use]
pub fn parallelism(mut self, n: u32) -> Self {
self.parallelism = Some(n);
self
}
#[must_use]
pub fn junit_xml(mut self, path: &str) -> Self {
self.junit_xml = Some(path.to_string());
self
}
#[must_use]
pub fn arg(mut self, arg: impl Into<String>) -> Self {
self.raw_args.push(arg.into());
self
}
}
impl TerraformCommand for TestCommand {
type Output = CommandOutput;
fn args(&self) -> Vec<String> {
let mut args = vec!["test".to_string()];
if let Some(ref filter) = self.filter {
args.push(format!("-filter={filter}"));
}
if self.json {
args.push("-json".to_string());
}
if let Some(ref dir) = self.test_directory {
args.push(format!("-test-directory={dir}"));
}
if self.verbose {
args.push("-verbose".to_string());
}
for (name, value) in &self.vars {
args.push(format!("-var={name}={value}"));
}
for file in &self.var_files {
args.push(format!("-var-file={file}"));
}
if let Some(n) = self.parallelism {
args.push(format!("-parallelism={n}"));
}
if let Some(ref path) = self.junit_xml {
args.push(format!("-junit-xml={path}"));
}
args.extend(self.raw_args.clone());
args
}
async fn execute(&self, tf: &Terraform) -> Result<CommandOutput> {
exec::run_terraform(tf, self.args()).await
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_args() {
let cmd = TestCommand::new();
assert_eq!(cmd.args(), vec!["test"]);
}
#[test]
fn with_filter() {
let cmd = TestCommand::new().filter("my_test");
assert_eq!(cmd.args(), vec!["test", "-filter=my_test"]);
}
#[test]
fn with_json_and_verbose() {
let cmd = TestCommand::new().json().verbose();
let args = cmd.args();
assert_eq!(args[0], "test");
assert!(args.contains(&"-json".to_string()));
assert!(args.contains(&"-verbose".to_string()));
}
#[test]
fn with_test_directory() {
let cmd = TestCommand::new().test_directory("integration");
assert_eq!(cmd.args(), vec!["test", "-test-directory=integration"]);
}
#[test]
fn with_vars() {
let cmd = TestCommand::new()
.var("region", "us-west-2")
.var("env", "staging");
let args = cmd.args();
assert!(args.contains(&"-var=region=us-west-2".to_string()));
assert!(args.contains(&"-var=env=staging".to_string()));
}
#[test]
fn with_var_files() {
let cmd = TestCommand::new()
.var_file("prod.tfvars")
.var_file("overrides.tfvars");
let args = cmd.args();
assert!(args.contains(&"-var-file=prod.tfvars".to_string()));
assert!(args.contains(&"-var-file=overrides.tfvars".to_string()));
}
#[test]
fn with_parallelism() {
let cmd = TestCommand::new().parallelism(4);
let args = cmd.args();
assert!(args.contains(&"-parallelism=4".to_string()));
}
#[test]
fn with_junit_xml() {
let cmd = TestCommand::new().junit_xml("results.xml");
let args = cmd.args();
assert!(args.contains(&"-junit-xml=results.xml".to_string()));
}
#[test]
fn all_options() {
let cmd = TestCommand::new()
.filter("vpc_test")
.json()
.test_directory("e2e")
.verbose()
.var("region", "us-west-2")
.var_file("prod.tfvars")
.parallelism(8)
.junit_xml("results.xml");
let args = cmd.args();
assert_eq!(args[0], "test");
assert!(args.contains(&"-filter=vpc_test".to_string()));
assert!(args.contains(&"-json".to_string()));
assert!(args.contains(&"-test-directory=e2e".to_string()));
assert!(args.contains(&"-verbose".to_string()));
assert!(args.contains(&"-var=region=us-west-2".to_string()));
assert!(args.contains(&"-var-file=prod.tfvars".to_string()));
assert!(args.contains(&"-parallelism=8".to_string()));
assert!(args.contains(&"-junit-xml=results.xml".to_string()));
}
}