@ -146,8 +146,9 @@ func TestTest_Runs(t *testing.T) {
} ,
"simple_fail" : {
expectedOut : [ ] string { "0 passed, 1 failed." } ,
expectedErr : [ ] string { "invalid value" } ,
code : 1 ,
expectedErr : [ ] string { "invalid value" , ` │ - "bar"
│ + "zap" ` } ,
code : 1 ,
} ,
"custom_condition_checks" : {
expectedOut : [ ] string { "0 passed, 1 failed." } ,
@ -301,8 +302,10 @@ func TestTest_Runs(t *testing.T) {
} ,
"ephemeral_input_with_error" : {
expectedOut : [ ] string { "Error message refers to ephemeral values" , "1 passed, 1 failed." } ,
expectedErr : [ ] string { "Test assertion failed" , "has an ephemeral value" } ,
code : 1 ,
expectedErr : [ ] string { "Test assertion failed" ,
` │ - "(ephemeral value)"
│ + "bar" ` } ,
code : 1 ,
} ,
"ephemeral_resource" : {
expectedOut : [ ] string { "0 passed, 1 failed." } ,
@ -837,6 +840,495 @@ func TestTest_ProviderAlias(t *testing.T) {
}
}
func TestTest_ComplexCondition ( t * testing . T ) {
td := t . TempDir ( )
testCopyDir ( t , testFixturePath ( path . Join ( "test" , "complex_condition" ) ) , td )
defer testChdir ( t , td ) ( )
provider := testing_command . NewProvider ( nil )
providerSource , close := newMockProviderSource ( t , map [ string ] [ ] string { "test" : { "1.0.0" } } )
defer close ( )
streams , done := terminal . StreamsForTesting ( t )
view := views . NewView ( streams )
ui := new ( cli . MockUi )
meta := Meta {
testingOverrides : metaOverridesForProvider ( provider . Provider ) ,
Ui : ui ,
View : view ,
Streams : streams ,
ProviderSource : providerSource ,
}
init := & InitCommand {
Meta : meta ,
}
output := done ( t )
if code := init . Run ( [ ] string { "-no-color" } ) ; code != 0 {
t . Fatalf ( "expected status code 0 but got %d: %s" , code , output . All ( ) )
}
// Reset the streams for the next command.
streams , done = terminal . StreamsForTesting ( t )
meta . Streams = streams
meta . View = views . NewView ( streams )
command := & TestCommand {
Meta : meta ,
}
code := command . Run ( [ ] string { "-no-color" } )
output = done ( t )
printedOutput := false
if code != 1 {
printedOutput = true
t . Errorf ( "expected status code 1 but got %d: %s" , code , output . All ( ) )
}
expectedOut := ` main . tftest . hcl ... in progress
run "validate_diff_types" ... fail
run "validate_output" ... fail
run "validate_complex_output" ... fail
run "validate_complex_output_sensitive" ... fail
run "validate_complex_output_pass" ... pass
main . tftest . hcl ... tearing down
main . tftest . hcl ... fail
Failure ! 1 passed , 4 failed .
`
expectedErr := `
Error : Test assertion failed
on main . tftest . hcl line 37 , in run "validate_diff_types" :
37 : condition = var . tr1 == var . tr2
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ Warning : LHS and RHS values are of different types
expected to fail
Error : Test assertion failed
on main . tftest . hcl line 44 , in run "validate_output" :
44 : condition = output . foo == var . foo
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ Diff :
│ -- - actual
│ ++ + expected
│ {
│ - "bar" : "notbaz" ,
│ + "bar" : "baz" ,
│ "matches" : "matches" ,
│ - "qux" : "quux" ,
│ - "xuq" : "xuq"
│ + "qux" : "qux" ,
│ + "xuq" : "nope"
│ }
expected to fail due to different values
Error : Test assertion failed
on main . tftest . hcl line 52 , in run "validate_complex_output" :
52 : condition = output . complex == var . bar
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ Warning : LHS and RHS values are of different types
│ Diff :
│ -- - actual
│ ++ + expected
│ {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ - "qux" : "quux"
│ + "qux" : "qux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
expected to fail
Error : Test assertion failed
on main . tftest . hcl line 60 , in run "validate_complex_output_sensitive" :
60 : condition = output . complex == output . complex_sensitive
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ Diff :
│ -- - actual
│ ++ + expected
│ - {
│ - "root" : [
│ - {
│ - "bar" : [
│ - 1
│ - ] ,
│ - "qux" : "quux"
│ - } ,
│ - {
│ - "bar" : [
│ - 2
│ - ] ,
│ - "qux" : "quux"
│ - }
│ - ]
│ - }
│ + "(sensitive value)"
expected to fail
`
if diff := cmp . Diff ( output . Stdout ( ) , expectedOut ) ; len ( diff ) > 0 {
t . Errorf ( "\nexpected: \n%s\ngot: %s\ndiff: %s" , expectedOut , output . All ( ) , diff )
}
if diff := cmp . Diff ( output . Stderr ( ) , expectedErr ) ; len ( diff ) > 0 {
t . Errorf ( "\nexpected stderr: \n%s\ngot: %s\ndiff: %s" , expectedErr , output . Stderr ( ) , diff )
}
if provider . ResourceCount ( ) > 0 {
if ! printedOutput {
t . Errorf ( "should have deleted all resources on completion but left %s\n\n%s" , provider . ResourceString ( ) , output . All ( ) )
} else {
t . Errorf ( "should have deleted all resources on completion but left %s" , provider . ResourceString ( ) )
}
}
}
func TestTest_ComplexConditionVerbose ( t * testing . T ) {
td := t . TempDir ( )
testCopyDir ( t , testFixturePath ( path . Join ( "test" , "complex_condition" ) ) , td )
defer testChdir ( t , td ) ( )
provider := testing_command . NewProvider ( nil )
providerSource , close := newMockProviderSource ( t , map [ string ] [ ] string { "test" : { "1.0.0" } } )
defer close ( )
streams , done := terminal . StreamsForTesting ( t )
view := views . NewView ( streams )
ui := new ( cli . MockUi )
meta := Meta {
testingOverrides : metaOverridesForProvider ( provider . Provider ) ,
Ui : ui ,
View : view ,
Streams : streams ,
ProviderSource : providerSource ,
}
init := & InitCommand {
Meta : meta ,
}
output := done ( t )
if code := init . Run ( [ ] string { "-no-color" } ) ; code != 0 {
t . Fatalf ( "expected status code 0 but got %d: %s" , code , output . All ( ) )
}
// Reset the streams for the next command.
streams , done = terminal . StreamsForTesting ( t )
meta . Streams = streams
meta . View = views . NewView ( streams )
command := & TestCommand {
Meta : meta ,
}
code := command . Run ( [ ] string { "-no-color" , "-verbose" } )
output = done ( t )
printedOutput := false
if code != 1 {
printedOutput = true
t . Errorf ( "expected status code 1 but got %d: %s" , code , output . All ( ) )
}
expectedErr := `
Error : Test assertion failed
on main . tftest . hcl line 37 , in run "validate_diff_types" :
37 : condition = var . tr1 == var . tr2
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ LHS :
│ {
│ "iops" : null ,
│ "size" : 60
│ }
│ RHS :
│ {
│ "iops" : null ,
│ "size" : 60
│ }
│ Warning : LHS and RHS values are of different types
│ var . tr1 is {
│ "iops" : null ,
│ "size" : 60
│ }
│ var . tr2 is {
│ "iops" : null ,
│ "size" : 60
│ }
expected to fail
Error : Test assertion failed
on main . tftest . hcl line 44 , in run "validate_output" :
44 : condition = output . foo == var . foo
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ LHS :
│ {
│ "bar" : "notbaz" ,
│ "matches" : "matches" ,
│ "qux" : "quux" ,
│ "xuq" : "xuq"
│ }
│ RHS :
│ {
│ "bar" : "baz" ,
│ "matches" : "matches" ,
│ "qux" : "qux" ,
│ "xuq" : "nope"
│ }
│ Diff :
│ -- - actual
│ ++ + expected
│ {
│ - "bar" : "notbaz" ,
│ + "bar" : "baz" ,
│ "matches" : "matches" ,
│ - "qux" : "quux" ,
│ - "xuq" : "xuq"
│ + "qux" : "qux" ,
│ + "xuq" : "nope"
│ }
│ output . foo is {
│ "bar" : "notbaz" ,
│ "matches" : "matches" ,
│ "qux" : "quux" ,
│ "xuq" : "xuq"
│ }
│ var . foo is {
│ "bar" : "baz" ,
│ "matches" : "matches" ,
│ "qux" : "qux" ,
│ "xuq" : "nope"
│ }
expected to fail due to different values
Error : Test assertion failed
on main . tftest . hcl line 52 , in run "validate_complex_output" :
52 : condition = output . complex == var . bar
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ LHS :
│ {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "quux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ RHS :
│ {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "qux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ Warning : LHS and RHS values are of different types
│ Diff :
│ -- - actual
│ ++ + expected
│ {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ - "qux" : "quux"
│ + "qux" : "qux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ output . complex is {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "quux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ var . bar is {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "qux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
expected to fail
Error : Test assertion failed
on main . tftest . hcl line 60 , in run "validate_complex_output_sensitive" :
60 : condition = output . complex == output . complex_sensitive
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ LHS :
│ {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "quux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ RHS :
│ "(sensitive value)"
│ Diff :
│ -- - actual
│ ++ + expected
│ - {
│ - "root" : [
│ - {
│ - "bar" : [
│ - 1
│ - ] ,
│ - "qux" : "quux"
│ - } ,
│ - {
│ - "bar" : [
│ - 2
│ - ] ,
│ - "qux" : "quux"
│ - }
│ - ]
│ - }
│ + "(sensitive value)"
│ output . complex is {
│ "root" : [
│ {
│ "bar" : [
│ 1
│ ] ,
│ "qux" : "quux"
│ } ,
│ {
│ "bar" : [
│ 2
│ ] ,
│ "qux" : "quux"
│ }
│ ]
│ }
│ output . complex_sensitive is "(sensitive value)"
expected to fail
`
outputs := [ ] string {
"main.tftest.hcl... in progress" ,
" run \"validate_diff_types\"... fail" ,
" run \"validate_output\"... fail" ,
" run \"validate_complex_output\"... fail" ,
" run \"validate_complex_output_sensitive\"... fail" ,
" run \"validate_complex_output_pass\"... pass" ,
"main.tftest.hcl... tearing down" ,
"main.tftest.hcl... fail" ,
"Failure! 1 passed, 4 failed." ,
}
stdout := output . Stdout ( )
for _ , expected := range outputs {
if ! strings . Contains ( stdout , expected ) {
t . Errorf ( "output didn't contain expected output %q" , expected )
}
}
if diff := cmp . Diff ( output . Stderr ( ) , expectedErr ) ; len ( diff ) > 0 {
t . Errorf ( "\nexpected stderr: \n%s\ngot: %s\ndiff: %s" , expectedErr , output . Stderr ( ) , diff )
}
if provider . ResourceCount ( ) > 0 {
if ! printedOutput {
t . Errorf ( "should have deleted all resources on completion but left %s\n\n%s" , provider . ResourceString ( ) , output . All ( ) )
} else {
t . Errorf ( "should have deleted all resources on completion but left %s" , provider . ResourceString ( ) )
}
}
}
func TestTest_ModuleDependencies ( t * testing . T ) {
td := t . TempDir ( )
testCopyDir ( t , testFixturePath ( path . Join ( "test" , "with_setup_module" ) ) , td )
@ -2027,8 +2519,13 @@ Error: Test assertion failed
on main . tftest . hcl line 8 , in run "first" :
8 : condition = test_resource . resource . value == output . null_output
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ output . null_output is null
│ test_resource . resource . value is "bar"
│ Warning : LHS and RHS values are of different types
│ Diff :
│ -- - actual
│ ++ + expected
│ - "bar"
│ + null
this is always going to fail
` ,
@ -2210,8 +2707,8 @@ func TestTest_SensitiveInputValues(t *testing.T) {
code := c . Run ( [ ] string { "-no-color" , "-verbose" } )
output = done ( t )
if code != 0 {
t . Errorf ( "expected status code 0 but got %d", code )
if code != 1 {
t . Errorf ( "expected status code 1 but got %d", code )
}
expected := ` main . tftest . hcl ... in progress
@ -2233,22 +2730,77 @@ resource "test_resource" "resource" {
}
Outputs :
password = ( sensitive value )
run "test_failed" ... fail
# test_resource . resource :
resource "test_resource" "resource" {
destroy_fail = false
id = "9ddca5a9"
value = ( sensitive value )
}
Outputs :
password = ( sensitive value )
main . tftest . hcl ... tearing down
main . tftest . hcl ... pass
main . tftest . hcl ... fail
Success ! 2 passed , 0 failed .
Failure! 2 passed , 1 failed .
`
actual := output . All ( )
expectedErr := `
Error : Test assertion failed
on main . tftest . hcl line 27 , in run "test_failed" :
27 : condition = var . complex == {
28 : foo = "bar"
29 : baz = test_resource . resource . id
30 : }
├ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
│ LHS :
│ {
│ "baz" : "(sensitive value)" ,
│ "foo" : "bar"
│ }
│ RHS :
│ {
│ "baz" : "9ddca5a9" ,
│ "foo" : "bar"
│ }
│ Diff :
│ -- - actual
│ ++ + expected
│ {
│ - "baz" : "(sensitive value)" ,
│ + "baz" : "9ddca5a9" ,
│ "foo" : "bar"
│ }
│ test_resource . resource . id is "9ddca5a9"
│ var . complex is {
│ "baz" : "(sensitive value)" ,
│ "foo" : "bar"
│ }
expected to fail
`
actual := output . Stdout ( )
if diff := cmp . Diff ( actual , expected ) ; len ( diff ) > 0 {
t . Errorf ( "output didn't match expected:\nexpected:\n%s\nactual:\n%s\ndiff:\n%s" , expected , actual , diff )
}
if diff := cmp . Diff ( output . Stderr ( ) , expectedErr ) ; len ( diff ) > 0 {
t . Errorf ( "stderr didn't match expected:\nexpected:\n%s\nactual:\n%s\ndiff:\n%s" , expectedErr , output . Stderr ( ) , diff )
}
if provider . ResourceCount ( ) > 0 {
t . Errorf ( "should have deleted all resources on completion but left %v" , provider . ResourceString ( ) )
}
@ -2804,7 +3356,7 @@ func TestTest_JUnitOutput(t *testing.T) {
actualOut = timestampRegexp . ReplaceAll ( actualOut , [ ] byte ( "timestamp=\"TIMESTAMP_REDACTED\"" ) )
if ! bytes . Equal ( actualOut , expectedOutput ) {
t . Fatalf ( "wanted XML:\n%s\n got XML:\n%s\n ", string ( expectedOutput ) , string ( actualOut ) )
t . Fatalf ( "wanted XML:\n%s\n got XML:\n%s\n diff:%s\n ", string ( expectedOutput ) , string ( actualOut ) , cmp . Diff ( expectedOutput , actualOut ) )
}
if provider . ResourceCount ( ) > 0 {