github.com/terramate-io/tf@v0.0.0-20230830114523-fce866b4dfcd/command/views/test_test.go (about) 1 package views 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/google/go-cmp/cmp" 8 "github.com/zclconf/go-cty/cty" 9 10 "github.com/terramate-io/tf/addrs" 11 "github.com/terramate-io/tf/command/arguments" 12 "github.com/terramate-io/tf/configs" 13 "github.com/terramate-io/tf/configs/configschema" 14 "github.com/terramate-io/tf/moduletest" 15 "github.com/terramate-io/tf/plans" 16 "github.com/terramate-io/tf/providers" 17 "github.com/terramate-io/tf/states" 18 "github.com/terramate-io/tf/terminal" 19 "github.com/terramate-io/tf/tfdiags" 20 ) 21 22 func TestTestHuman_Conclusion(t *testing.T) { 23 tcs := map[string]struct { 24 Suite *moduletest.Suite 25 Expected string 26 }{ 27 "no tests": { 28 Suite: &moduletest.Suite{}, 29 Expected: "\nExecuted 0 tests.\n", 30 }, 31 32 "only skipped tests": { 33 Suite: &moduletest.Suite{ 34 Status: moduletest.Skip, 35 Files: map[string]*moduletest.File{ 36 "descriptive_test_name.tftest.hcl": { 37 Name: "descriptive_test_name.tftest.hcl", 38 Status: moduletest.Skip, 39 Runs: []*moduletest.Run{ 40 { 41 Name: "test_one", 42 Status: moduletest.Skip, 43 }, 44 { 45 Name: "test_two", 46 Status: moduletest.Skip, 47 }, 48 { 49 Name: "test_three", 50 Status: moduletest.Skip, 51 }, 52 }, 53 }, 54 "other_descriptive_test_name.tftest.hcl": { 55 Name: "other_descriptive_test_name.tftest.hcl", 56 Status: moduletest.Skip, 57 Runs: []*moduletest.Run{ 58 { 59 Name: "test_one", 60 Status: moduletest.Skip, 61 }, 62 { 63 Name: "test_two", 64 Status: moduletest.Skip, 65 }, 66 { 67 Name: "test_three", 68 Status: moduletest.Skip, 69 }, 70 }, 71 }, 72 }, 73 }, 74 Expected: "\nExecuted 0 tests, 6 skipped.\n", 75 }, 76 77 "only passed tests": { 78 Suite: &moduletest.Suite{ 79 Status: moduletest.Pass, 80 Files: map[string]*moduletest.File{ 81 "descriptive_test_name.tftest.hcl": { 82 Name: "descriptive_test_name.tftest.hcl", 83 Status: moduletest.Pass, 84 Runs: []*moduletest.Run{ 85 { 86 Name: "test_one", 87 Status: moduletest.Pass, 88 }, 89 { 90 Name: "test_two", 91 Status: moduletest.Pass, 92 }, 93 { 94 Name: "test_three", 95 Status: moduletest.Pass, 96 }, 97 }, 98 }, 99 "other_descriptive_test_name.tftest.hcl": { 100 Name: "other_descriptive_test_name.tftest.hcl", 101 Status: moduletest.Pass, 102 Runs: []*moduletest.Run{ 103 { 104 Name: "test_one", 105 Status: moduletest.Pass, 106 }, 107 { 108 Name: "test_two", 109 Status: moduletest.Pass, 110 }, 111 { 112 Name: "test_three", 113 Status: moduletest.Pass, 114 }, 115 }, 116 }, 117 }, 118 }, 119 Expected: "\nSuccess! 6 passed, 0 failed.\n", 120 }, 121 122 "passed and skipped tests": { 123 Suite: &moduletest.Suite{ 124 Status: moduletest.Pass, 125 Files: map[string]*moduletest.File{ 126 "descriptive_test_name.tftest.hcl": { 127 Name: "descriptive_test_name.tftest.hcl", 128 Status: moduletest.Pass, 129 Runs: []*moduletest.Run{ 130 { 131 Name: "test_one", 132 Status: moduletest.Pass, 133 }, 134 { 135 Name: "test_two", 136 Status: moduletest.Skip, 137 }, 138 { 139 Name: "test_three", 140 Status: moduletest.Pass, 141 }, 142 }, 143 }, 144 "other_descriptive_test_name.tftest.hcl": { 145 Name: "other_descriptive_test_name.tftest.hcl", 146 Status: moduletest.Pass, 147 Runs: []*moduletest.Run{ 148 { 149 Name: "test_one", 150 Status: moduletest.Skip, 151 }, 152 { 153 Name: "test_two", 154 Status: moduletest.Pass, 155 }, 156 { 157 Name: "test_three", 158 Status: moduletest.Pass, 159 }, 160 }, 161 }, 162 }, 163 }, 164 Expected: "\nSuccess! 4 passed, 0 failed, 2 skipped.\n", 165 }, 166 167 "only failed tests": { 168 Suite: &moduletest.Suite{ 169 Status: moduletest.Fail, 170 Files: map[string]*moduletest.File{ 171 "descriptive_test_name.tftest.hcl": { 172 Name: "descriptive_test_name.tftest.hcl", 173 Status: moduletest.Fail, 174 Runs: []*moduletest.Run{ 175 { 176 Name: "test_one", 177 Status: moduletest.Fail, 178 }, 179 { 180 Name: "test_two", 181 Status: moduletest.Fail, 182 }, 183 { 184 Name: "test_three", 185 Status: moduletest.Fail, 186 }, 187 }, 188 }, 189 "other_descriptive_test_name.tftest.hcl": { 190 Name: "other_descriptive_test_name.tftest.hcl", 191 Status: moduletest.Fail, 192 Runs: []*moduletest.Run{ 193 { 194 Name: "test_one", 195 Status: moduletest.Fail, 196 }, 197 { 198 Name: "test_two", 199 Status: moduletest.Fail, 200 }, 201 { 202 Name: "test_three", 203 Status: moduletest.Fail, 204 }, 205 }, 206 }, 207 }, 208 }, 209 Expected: "\nFailure! 0 passed, 6 failed.\n", 210 }, 211 212 "failed and skipped tests": { 213 Suite: &moduletest.Suite{ 214 Status: moduletest.Fail, 215 Files: map[string]*moduletest.File{ 216 "descriptive_test_name.tftest.hcl": { 217 Name: "descriptive_test_name.tftest.hcl", 218 Status: moduletest.Fail, 219 Runs: []*moduletest.Run{ 220 { 221 Name: "test_one", 222 Status: moduletest.Fail, 223 }, 224 { 225 Name: "test_two", 226 Status: moduletest.Skip, 227 }, 228 { 229 Name: "test_three", 230 Status: moduletest.Fail, 231 }, 232 }, 233 }, 234 "other_descriptive_test_name.tftest.hcl": { 235 Name: "other_descriptive_test_name.tftest.hcl", 236 Status: moduletest.Fail, 237 Runs: []*moduletest.Run{ 238 { 239 Name: "test_one", 240 Status: moduletest.Fail, 241 }, 242 { 243 Name: "test_two", 244 Status: moduletest.Fail, 245 }, 246 { 247 Name: "test_three", 248 Status: moduletest.Skip, 249 }, 250 }, 251 }, 252 }, 253 }, 254 Expected: "\nFailure! 0 passed, 4 failed, 2 skipped.\n", 255 }, 256 257 "failed, passed and skipped tests": { 258 Suite: &moduletest.Suite{ 259 Status: moduletest.Fail, 260 Files: map[string]*moduletest.File{ 261 "descriptive_test_name.tftest.hcl": { 262 Name: "descriptive_test_name.tftest.hcl", 263 Status: moduletest.Fail, 264 Runs: []*moduletest.Run{ 265 { 266 Name: "test_one", 267 Status: moduletest.Fail, 268 }, 269 { 270 Name: "test_two", 271 Status: moduletest.Pass, 272 }, 273 { 274 Name: "test_three", 275 Status: moduletest.Skip, 276 }, 277 }, 278 }, 279 "other_descriptive_test_name.tftest.hcl": { 280 Name: "other_descriptive_test_name.tftest.hcl", 281 Status: moduletest.Fail, 282 Runs: []*moduletest.Run{ 283 { 284 Name: "test_one", 285 Status: moduletest.Skip, 286 }, 287 { 288 Name: "test_two", 289 Status: moduletest.Fail, 290 }, 291 { 292 Name: "test_three", 293 Status: moduletest.Pass, 294 }, 295 }, 296 }, 297 }, 298 }, 299 Expected: "\nFailure! 2 passed, 2 failed, 2 skipped.\n", 300 }, 301 302 "failed and errored tests": { 303 Suite: &moduletest.Suite{ 304 Status: moduletest.Error, 305 Files: map[string]*moduletest.File{ 306 "descriptive_test_name.tftest.hcl": { 307 Name: "descriptive_test_name.tftest.hcl", 308 Status: moduletest.Error, 309 Runs: []*moduletest.Run{ 310 { 311 Name: "test_one", 312 Status: moduletest.Fail, 313 }, 314 { 315 Name: "test_two", 316 Status: moduletest.Error, 317 }, 318 { 319 Name: "test_three", 320 Status: moduletest.Fail, 321 }, 322 }, 323 }, 324 "other_descriptive_test_name.tftest.hcl": { 325 Name: "other_descriptive_test_name.tftest.hcl", 326 Status: moduletest.Error, 327 Runs: []*moduletest.Run{ 328 { 329 Name: "test_one", 330 Status: moduletest.Fail, 331 }, 332 { 333 Name: "test_two", 334 Status: moduletest.Error, 335 }, 336 { 337 Name: "test_three", 338 Status: moduletest.Error, 339 }, 340 }, 341 }, 342 }, 343 }, 344 Expected: "\nFailure! 0 passed, 6 failed.\n", 345 }, 346 347 "failed, errored, passed, and skipped tests": { 348 Suite: &moduletest.Suite{ 349 Status: moduletest.Error, 350 Files: map[string]*moduletest.File{ 351 "descriptive_test_name.tftest.hcl": { 352 Name: "descriptive_test_name.tftest.hcl", 353 Status: moduletest.Fail, 354 Runs: []*moduletest.Run{ 355 { 356 Name: "test_one", 357 Status: moduletest.Pass, 358 }, 359 { 360 Name: "test_two", 361 Status: moduletest.Pass, 362 }, 363 { 364 Name: "test_three", 365 Status: moduletest.Fail, 366 }, 367 }, 368 }, 369 "other_descriptive_test_name.tftest.hcl": { 370 Name: "other_descriptive_test_name.tftest.hcl", 371 Status: moduletest.Error, 372 Runs: []*moduletest.Run{ 373 { 374 Name: "test_one", 375 Status: moduletest.Error, 376 }, 377 { 378 Name: "test_two", 379 Status: moduletest.Skip, 380 }, 381 { 382 Name: "test_three", 383 Status: moduletest.Skip, 384 }, 385 }, 386 }, 387 }, 388 }, 389 Expected: "\nFailure! 2 passed, 2 failed, 2 skipped.\n", 390 }, 391 } 392 for name, tc := range tcs { 393 t.Run(name, func(t *testing.T) { 394 395 streams, done := terminal.StreamsForTesting(t) 396 view := NewTest(arguments.ViewHuman, NewView(streams)) 397 398 view.Conclusion(tc.Suite) 399 400 actual := done(t).Stdout() 401 expected := tc.Expected 402 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 403 t.Fatalf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 404 } 405 }) 406 } 407 } 408 409 func TestTestHuman_File(t *testing.T) { 410 tcs := map[string]struct { 411 File *moduletest.File 412 Expected string 413 }{ 414 "pass": { 415 File: &moduletest.File{Name: "main.tf", Status: moduletest.Pass}, 416 Expected: "main.tf... pass\n", 417 }, 418 419 "pending": { 420 File: &moduletest.File{Name: "main.tf", Status: moduletest.Pending}, 421 Expected: "main.tf... pending\n", 422 }, 423 424 "skip": { 425 File: &moduletest.File{Name: "main.tf", Status: moduletest.Skip}, 426 Expected: "main.tf... skip\n", 427 }, 428 429 "fail": { 430 File: &moduletest.File{Name: "main.tf", Status: moduletest.Fail}, 431 Expected: "main.tf... fail\n", 432 }, 433 434 "error": { 435 File: &moduletest.File{Name: "main.tf", Status: moduletest.Error}, 436 Expected: "main.tf... fail\n", 437 }, 438 } 439 for name, tc := range tcs { 440 t.Run(name, func(t *testing.T) { 441 442 streams, done := terminal.StreamsForTesting(t) 443 view := NewTest(arguments.ViewHuman, NewView(streams)) 444 445 view.File(tc.File) 446 447 actual := done(t).Stdout() 448 expected := tc.Expected 449 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 450 t.Fatalf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 451 } 452 }) 453 } 454 } 455 456 func TestTestHuman_Run(t *testing.T) { 457 tcs := map[string]struct { 458 Run *moduletest.Run 459 StdOut string 460 StdErr string 461 }{ 462 "pass": { 463 Run: &moduletest.Run{Name: "run_block", Status: moduletest.Pass}, 464 StdOut: " run \"run_block\"... pass\n", 465 }, 466 467 "pass_with_diags": { 468 Run: &moduletest.Run{ 469 Name: "run_block", 470 Status: moduletest.Pass, 471 Diagnostics: tfdiags.Diagnostics{tfdiags.Sourceless(tfdiags.Warning, "a warning occurred", "some warning happened during this test")}, 472 }, 473 StdOut: ` run "run_block"... pass 474 475 Warning: a warning occurred 476 477 some warning happened during this test 478 `, 479 }, 480 481 "pending": { 482 Run: &moduletest.Run{Name: "run_block", Status: moduletest.Pending}, 483 StdOut: " run \"run_block\"... pending\n", 484 }, 485 486 "skip": { 487 Run: &moduletest.Run{Name: "run_block", Status: moduletest.Skip}, 488 StdOut: " run \"run_block\"... skip\n", 489 }, 490 491 "fail": { 492 Run: &moduletest.Run{Name: "run_block", Status: moduletest.Fail}, 493 StdOut: " run \"run_block\"... fail\n", 494 }, 495 496 "fail_with_diags": { 497 Run: &moduletest.Run{ 498 Name: "run_block", 499 Status: moduletest.Fail, 500 Diagnostics: tfdiags.Diagnostics{ 501 tfdiags.Sourceless(tfdiags.Error, "a comparison failed", "details details details"), 502 tfdiags.Sourceless(tfdiags.Error, "a second comparison failed", "other details"), 503 }, 504 }, 505 StdOut: " run \"run_block\"... fail\n", 506 StdErr: ` 507 Error: a comparison failed 508 509 details details details 510 511 Error: a second comparison failed 512 513 other details 514 `, 515 }, 516 517 "error": { 518 Run: &moduletest.Run{Name: "run_block", Status: moduletest.Error}, 519 StdOut: " run \"run_block\"... fail\n", 520 }, 521 522 "error_with_diags": { 523 Run: &moduletest.Run{ 524 Name: "run_block", 525 Status: moduletest.Error, 526 Diagnostics: tfdiags.Diagnostics{tfdiags.Sourceless(tfdiags.Error, "an error occurred", "something bad happened during this test")}, 527 }, 528 StdOut: " run \"run_block\"... fail\n", 529 StdErr: ` 530 Error: an error occurred 531 532 something bad happened during this test 533 `, 534 }, 535 "verbose_plan": { 536 Run: &moduletest.Run{ 537 Name: "run_block", 538 Status: moduletest.Pass, 539 Config: &configs.TestRun{ 540 Command: configs.PlanTestCommand, 541 }, 542 Verbose: &moduletest.Verbose{ 543 Plan: &plans.Plan{ 544 Changes: &plans.Changes{ 545 Resources: []*plans.ResourceInstanceChangeSrc{ 546 { 547 Addr: addrs.AbsResourceInstance{ 548 Module: addrs.RootModuleInstance, 549 Resource: addrs.ResourceInstance{ 550 Resource: addrs.Resource{ 551 Mode: addrs.ManagedResourceMode, 552 Type: "test_resource", 553 Name: "creating", 554 }, 555 }, 556 }, 557 PrevRunAddr: addrs.AbsResourceInstance{ 558 Module: addrs.RootModuleInstance, 559 Resource: addrs.ResourceInstance{ 560 Resource: addrs.Resource{ 561 Mode: addrs.ManagedResourceMode, 562 Type: "test_resource", 563 Name: "creating", 564 }, 565 }, 566 }, 567 ProviderAddr: addrs.AbsProviderConfig{ 568 Module: addrs.RootModule, 569 Provider: addrs.Provider{ 570 Hostname: addrs.DefaultProviderRegistryHost, 571 Namespace: "hashicorp", 572 Type: "test", 573 }, 574 }, 575 ChangeSrc: plans.ChangeSrc{ 576 Action: plans.Create, 577 After: dynamicValue( 578 t, 579 cty.ObjectVal(map[string]cty.Value{ 580 "value": cty.StringVal("Hello, world!"), 581 }), 582 cty.Object(map[string]cty.Type{ 583 "value": cty.String, 584 })), 585 }, 586 }, 587 }, 588 }, 589 }, 590 State: states.NewState(), // empty state 591 Config: &configs.Config{}, 592 Providers: map[addrs.Provider]providers.ProviderSchema{ 593 addrs.Provider{ 594 Hostname: addrs.DefaultProviderRegistryHost, 595 Namespace: "hashicorp", 596 Type: "test", 597 }: { 598 ResourceTypes: map[string]providers.Schema{ 599 "test_resource": { 600 Block: &configschema.Block{ 601 Attributes: map[string]*configschema.Attribute{ 602 "value": { 603 Type: cty.String, 604 }, 605 }, 606 }, 607 }, 608 }, 609 }, 610 }, 611 }, 612 }, 613 StdOut: ` run "run_block"... pass 614 615 Terraform used the selected providers to generate the following execution 616 plan. Resource actions are indicated with the following symbols: 617 + create 618 619 Terraform will perform the following actions: 620 621 # test_resource.creating will be created 622 + resource "test_resource" "creating" { 623 + value = "Hello, world!" 624 } 625 626 Plan: 1 to add, 0 to change, 0 to destroy. 627 `, 628 }, 629 "verbose_apply": { 630 Run: &moduletest.Run{ 631 Name: "run_block", 632 Status: moduletest.Pass, 633 Config: &configs.TestRun{ 634 Command: configs.ApplyTestCommand, 635 }, 636 Verbose: &moduletest.Verbose{ 637 Plan: &plans.Plan{}, // empty plan 638 State: states.BuildState(func(state *states.SyncState) { 639 state.SetResourceInstanceCurrent( 640 addrs.AbsResourceInstance{ 641 Module: addrs.RootModuleInstance, 642 Resource: addrs.ResourceInstance{ 643 Resource: addrs.Resource{ 644 Mode: addrs.ManagedResourceMode, 645 Type: "test_resource", 646 Name: "creating", 647 }, 648 }, 649 }, 650 &states.ResourceInstanceObjectSrc{ 651 AttrsJSON: []byte(`{"value":"foobar"}`), 652 }, 653 addrs.AbsProviderConfig{ 654 Module: addrs.RootModule, 655 Provider: addrs.Provider{ 656 Hostname: addrs.DefaultProviderRegistryHost, 657 Namespace: "hashicorp", 658 Type: "test", 659 }, 660 }) 661 }), 662 Config: &configs.Config{}, 663 Providers: map[addrs.Provider]providers.ProviderSchema{ 664 addrs.Provider{ 665 Hostname: addrs.DefaultProviderRegistryHost, 666 Namespace: "hashicorp", 667 Type: "test", 668 }: { 669 ResourceTypes: map[string]providers.Schema{ 670 "test_resource": { 671 Block: &configschema.Block{ 672 Attributes: map[string]*configschema.Attribute{ 673 "value": { 674 Type: cty.String, 675 }, 676 }, 677 }, 678 }, 679 }, 680 }, 681 }, 682 }, 683 }, 684 StdOut: ` run "run_block"... pass 685 # test_resource.creating: 686 resource "test_resource" "creating" { 687 value = "foobar" 688 } 689 `, 690 }, 691 } 692 for name, tc := range tcs { 693 t.Run(name, func(t *testing.T) { 694 file := &moduletest.File{ 695 Name: "main.tftest.hcl", 696 } 697 698 streams, done := terminal.StreamsForTesting(t) 699 view := NewTest(arguments.ViewHuman, NewView(streams)) 700 701 view.Run(tc.Run, file) 702 703 output := done(t) 704 actual, expected := output.Stdout(), tc.StdOut 705 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 706 t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 707 } 708 709 actual, expected = output.Stderr(), tc.StdErr 710 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 711 t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 712 } 713 }) 714 } 715 } 716 717 func TestTestHuman_DestroySummary(t *testing.T) { 718 tcs := map[string]struct { 719 diags tfdiags.Diagnostics 720 run *moduletest.Run 721 file *moduletest.File 722 state *states.State 723 stdout string 724 stderr string 725 }{ 726 "empty": { 727 diags: nil, 728 file: &moduletest.File{Name: "main.tftest.hcl"}, 729 state: states.NewState(), 730 }, 731 "empty_state_only_warnings": { 732 diags: tfdiags.Diagnostics{ 733 tfdiags.Sourceless(tfdiags.Warning, "first warning", "some thing not very bad happened"), 734 tfdiags.Sourceless(tfdiags.Warning, "second warning", "some thing not very bad happened again"), 735 }, 736 file: &moduletest.File{Name: "main.tftest.hcl"}, 737 state: states.NewState(), 738 stdout: ` 739 Warning: first warning 740 741 some thing not very bad happened 742 743 Warning: second warning 744 745 some thing not very bad happened again 746 `, 747 }, 748 "empty_state_with_errors": { 749 diags: tfdiags.Diagnostics{ 750 tfdiags.Sourceless(tfdiags.Warning, "first warning", "some thing not very bad happened"), 751 tfdiags.Sourceless(tfdiags.Warning, "second warning", "some thing not very bad happened again"), 752 tfdiags.Sourceless(tfdiags.Error, "first error", "this time it is very bad"), 753 }, 754 file: &moduletest.File{Name: "main.tftest.hcl"}, 755 state: states.NewState(), 756 stdout: ` 757 Warning: first warning 758 759 some thing not very bad happened 760 761 Warning: second warning 762 763 some thing not very bad happened again 764 `, 765 stderr: `Terraform encountered an error destroying resources created while executing 766 main.tftest.hcl. 767 768 Error: first error 769 770 this time it is very bad 771 `, 772 }, 773 "error_from_run": { 774 diags: tfdiags.Diagnostics{ 775 tfdiags.Sourceless(tfdiags.Error, "first error", "this time it is very bad"), 776 }, 777 run: &moduletest.Run{Name: "run_block"}, 778 file: &moduletest.File{Name: "main.tftest.hcl"}, 779 state: states.NewState(), 780 stderr: `Terraform encountered an error destroying resources created while executing 781 main.tftest.hcl/run_block. 782 783 Error: first error 784 785 this time it is very bad 786 `, 787 }, 788 "state_only_warnings": { 789 diags: tfdiags.Diagnostics{ 790 tfdiags.Sourceless(tfdiags.Warning, "first warning", "some thing not very bad happened"), 791 tfdiags.Sourceless(tfdiags.Warning, "second warning", "some thing not very bad happened again"), 792 }, 793 file: &moduletest.File{Name: "main.tftest.hcl"}, 794 state: states.BuildState(func(state *states.SyncState) { 795 state.SetResourceInstanceCurrent( 796 addrs.Resource{ 797 Mode: addrs.ManagedResourceMode, 798 Type: "test", 799 Name: "foo", 800 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 801 &states.ResourceInstanceObjectSrc{ 802 Status: states.ObjectReady, 803 }, 804 addrs.AbsProviderConfig{ 805 Module: addrs.RootModule, 806 Provider: addrs.NewDefaultProvider("test"), 807 }) 808 state.SetResourceInstanceCurrent( 809 addrs.Resource{ 810 Mode: addrs.ManagedResourceMode, 811 Type: "test", 812 Name: "bar", 813 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 814 &states.ResourceInstanceObjectSrc{ 815 Status: states.ObjectReady, 816 }, 817 addrs.AbsProviderConfig{ 818 Module: addrs.RootModule, 819 Provider: addrs.NewDefaultProvider("test"), 820 }) 821 state.SetResourceInstanceDeposed( 822 addrs.Resource{ 823 Mode: addrs.ManagedResourceMode, 824 Type: "test", 825 Name: "bar", 826 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 827 "0fcb640a", 828 &states.ResourceInstanceObjectSrc{ 829 Status: states.ObjectReady, 830 }, 831 addrs.AbsProviderConfig{ 832 Module: addrs.RootModule, 833 Provider: addrs.NewDefaultProvider("test"), 834 }) 835 }), 836 stdout: ` 837 Warning: first warning 838 839 some thing not very bad happened 840 841 Warning: second warning 842 843 some thing not very bad happened again 844 `, 845 stderr: ` 846 Terraform left the following resources in state after executing 847 main.tftest.hcl, and they need to be cleaned up manually: 848 - test.bar 849 - test.bar (0fcb640a) 850 - test.foo 851 `, 852 }, 853 "state_with_errors": { 854 diags: tfdiags.Diagnostics{ 855 tfdiags.Sourceless(tfdiags.Warning, "first warning", "some thing not very bad happened"), 856 tfdiags.Sourceless(tfdiags.Warning, "second warning", "some thing not very bad happened again"), 857 tfdiags.Sourceless(tfdiags.Error, "first error", "this time it is very bad"), 858 }, 859 file: &moduletest.File{Name: "main.tftest.hcl"}, 860 state: states.BuildState(func(state *states.SyncState) { 861 state.SetResourceInstanceCurrent( 862 addrs.Resource{ 863 Mode: addrs.ManagedResourceMode, 864 Type: "test", 865 Name: "foo", 866 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 867 &states.ResourceInstanceObjectSrc{ 868 Status: states.ObjectReady, 869 }, 870 addrs.AbsProviderConfig{ 871 Module: addrs.RootModule, 872 Provider: addrs.NewDefaultProvider("test"), 873 }) 874 state.SetResourceInstanceCurrent( 875 addrs.Resource{ 876 Mode: addrs.ManagedResourceMode, 877 Type: "test", 878 Name: "bar", 879 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 880 &states.ResourceInstanceObjectSrc{ 881 Status: states.ObjectReady, 882 }, 883 addrs.AbsProviderConfig{ 884 Module: addrs.RootModule, 885 Provider: addrs.NewDefaultProvider("test"), 886 }) 887 state.SetResourceInstanceDeposed( 888 addrs.Resource{ 889 Mode: addrs.ManagedResourceMode, 890 Type: "test", 891 Name: "bar", 892 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 893 "0fcb640a", 894 &states.ResourceInstanceObjectSrc{ 895 Status: states.ObjectReady, 896 }, 897 addrs.AbsProviderConfig{ 898 Module: addrs.RootModule, 899 Provider: addrs.NewDefaultProvider("test"), 900 }) 901 }), 902 stdout: ` 903 Warning: first warning 904 905 some thing not very bad happened 906 907 Warning: second warning 908 909 some thing not very bad happened again 910 `, 911 stderr: `Terraform encountered an error destroying resources created while executing 912 main.tftest.hcl. 913 914 Error: first error 915 916 this time it is very bad 917 918 Terraform left the following resources in state after executing 919 main.tftest.hcl, and they need to be cleaned up manually: 920 - test.bar 921 - test.bar (0fcb640a) 922 - test.foo 923 `, 924 }, 925 } 926 for name, tc := range tcs { 927 t.Run(name, func(t *testing.T) { 928 streams, done := terminal.StreamsForTesting(t) 929 view := NewTest(arguments.ViewHuman, NewView(streams)) 930 931 view.DestroySummary(tc.diags, tc.run, tc.file, tc.state) 932 933 output := done(t) 934 actual, expected := output.Stdout(), tc.stdout 935 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 936 t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 937 } 938 939 actual, expected = output.Stderr(), tc.stderr 940 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 941 t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 942 } 943 }) 944 } 945 } 946 947 func TestTestHuman_FatalInterruptSummary(t *testing.T) { 948 tcs := map[string]struct { 949 states map[*moduletest.Run]*states.State 950 run *moduletest.Run 951 created []*plans.ResourceInstanceChangeSrc 952 want string 953 }{ 954 "no_state_only_plan": { 955 states: make(map[*moduletest.Run]*states.State), 956 run: &moduletest.Run{ 957 Config: &configs.TestRun{}, 958 Name: "run_block", 959 }, 960 created: []*plans.ResourceInstanceChangeSrc{ 961 { 962 Addr: addrs.AbsResourceInstance{ 963 Module: addrs.RootModuleInstance, 964 Resource: addrs.ResourceInstance{ 965 Resource: addrs.Resource{ 966 Mode: addrs.ManagedResourceMode, 967 Type: "test_instance", 968 Name: "one", 969 }, 970 }, 971 }, 972 ChangeSrc: plans.ChangeSrc{ 973 Action: plans.Create, 974 }, 975 }, 976 { 977 Addr: addrs.AbsResourceInstance{ 978 Module: addrs.RootModuleInstance, 979 Resource: addrs.ResourceInstance{ 980 Resource: addrs.Resource{ 981 Mode: addrs.ManagedResourceMode, 982 Type: "test_instance", 983 Name: "two", 984 }, 985 }, 986 }, 987 ChangeSrc: plans.ChangeSrc{ 988 Action: plans.Create, 989 }, 990 }, 991 }, 992 want: ` 993 Terraform was interrupted while executing main.tftest.hcl, and may not have 994 performed the expected cleanup operations. 995 996 Terraform was in the process of creating the following resources for 997 "run_block" from the module under test, and they may not have been destroyed: 998 - test_instance.one 999 - test_instance.two 1000 `, 1001 }, 1002 "file_state_no_plan": { 1003 states: map[*moduletest.Run]*states.State{ 1004 nil: states.BuildState(func(state *states.SyncState) { 1005 state.SetResourceInstanceCurrent( 1006 addrs.AbsResourceInstance{ 1007 Module: addrs.RootModuleInstance, 1008 Resource: addrs.ResourceInstance{ 1009 Resource: addrs.Resource{ 1010 Mode: addrs.ManagedResourceMode, 1011 Type: "test_instance", 1012 Name: "one", 1013 }, 1014 }, 1015 }, 1016 &states.ResourceInstanceObjectSrc{}, 1017 addrs.AbsProviderConfig{}) 1018 1019 state.SetResourceInstanceCurrent( 1020 addrs.AbsResourceInstance{ 1021 Module: addrs.RootModuleInstance, 1022 Resource: addrs.ResourceInstance{ 1023 Resource: addrs.Resource{ 1024 Mode: addrs.ManagedResourceMode, 1025 Type: "test_instance", 1026 Name: "two", 1027 }, 1028 }, 1029 }, 1030 &states.ResourceInstanceObjectSrc{}, 1031 addrs.AbsProviderConfig{}) 1032 }), 1033 }, 1034 created: nil, 1035 want: ` 1036 Terraform was interrupted while executing main.tftest.hcl, and may not have 1037 performed the expected cleanup operations. 1038 1039 Terraform has already created the following resources from the module under 1040 test: 1041 - test_instance.one 1042 - test_instance.two 1043 `, 1044 }, 1045 "run_states_no_plan": { 1046 states: map[*moduletest.Run]*states.State{ 1047 &moduletest.Run{ 1048 Name: "setup_block", 1049 Config: &configs.TestRun{ 1050 Module: &configs.TestRunModuleCall{ 1051 Source: addrs.ModuleSourceLocal("../setup"), 1052 }, 1053 }, 1054 }: states.BuildState(func(state *states.SyncState) { 1055 state.SetResourceInstanceCurrent( 1056 addrs.AbsResourceInstance{ 1057 Module: addrs.RootModuleInstance, 1058 Resource: addrs.ResourceInstance{ 1059 Resource: addrs.Resource{ 1060 Mode: addrs.ManagedResourceMode, 1061 Type: "test_instance", 1062 Name: "one", 1063 }, 1064 }, 1065 }, 1066 &states.ResourceInstanceObjectSrc{}, 1067 addrs.AbsProviderConfig{}) 1068 1069 state.SetResourceInstanceCurrent( 1070 addrs.AbsResourceInstance{ 1071 Module: addrs.RootModuleInstance, 1072 Resource: addrs.ResourceInstance{ 1073 Resource: addrs.Resource{ 1074 Mode: addrs.ManagedResourceMode, 1075 Type: "test_instance", 1076 Name: "two", 1077 }, 1078 }, 1079 }, 1080 &states.ResourceInstanceObjectSrc{}, 1081 addrs.AbsProviderConfig{}) 1082 }), 1083 }, 1084 created: nil, 1085 want: ` 1086 Terraform was interrupted while executing main.tftest.hcl, and may not have 1087 performed the expected cleanup operations. 1088 1089 Terraform has already created the following resources for "setup_block" from 1090 "../setup": 1091 - test_instance.one 1092 - test_instance.two 1093 `, 1094 }, 1095 "all_states_with_plan": { 1096 states: map[*moduletest.Run]*states.State{ 1097 &moduletest.Run{ 1098 Name: "setup_block", 1099 Config: &configs.TestRun{ 1100 Module: &configs.TestRunModuleCall{ 1101 Source: addrs.ModuleSourceLocal("../setup"), 1102 }, 1103 }, 1104 }: states.BuildState(func(state *states.SyncState) { 1105 state.SetResourceInstanceCurrent( 1106 addrs.AbsResourceInstance{ 1107 Module: addrs.RootModuleInstance, 1108 Resource: addrs.ResourceInstance{ 1109 Resource: addrs.Resource{ 1110 Mode: addrs.ManagedResourceMode, 1111 Type: "test_instance", 1112 Name: "setup_one", 1113 }, 1114 }, 1115 }, 1116 &states.ResourceInstanceObjectSrc{}, 1117 addrs.AbsProviderConfig{}) 1118 1119 state.SetResourceInstanceCurrent( 1120 addrs.AbsResourceInstance{ 1121 Module: addrs.RootModuleInstance, 1122 Resource: addrs.ResourceInstance{ 1123 Resource: addrs.Resource{ 1124 Mode: addrs.ManagedResourceMode, 1125 Type: "test_instance", 1126 Name: "setup_two", 1127 }, 1128 }, 1129 }, 1130 &states.ResourceInstanceObjectSrc{}, 1131 addrs.AbsProviderConfig{}) 1132 }), 1133 nil: states.BuildState(func(state *states.SyncState) { 1134 state.SetResourceInstanceCurrent( 1135 addrs.AbsResourceInstance{ 1136 Module: addrs.RootModuleInstance, 1137 Resource: addrs.ResourceInstance{ 1138 Resource: addrs.Resource{ 1139 Mode: addrs.ManagedResourceMode, 1140 Type: "test_instance", 1141 Name: "one", 1142 }, 1143 }, 1144 }, 1145 &states.ResourceInstanceObjectSrc{}, 1146 addrs.AbsProviderConfig{}) 1147 1148 state.SetResourceInstanceCurrent( 1149 addrs.AbsResourceInstance{ 1150 Module: addrs.RootModuleInstance, 1151 Resource: addrs.ResourceInstance{ 1152 Resource: addrs.Resource{ 1153 Mode: addrs.ManagedResourceMode, 1154 Type: "test_instance", 1155 Name: "two", 1156 }, 1157 }, 1158 }, 1159 &states.ResourceInstanceObjectSrc{}, 1160 addrs.AbsProviderConfig{}) 1161 }), 1162 }, 1163 created: []*plans.ResourceInstanceChangeSrc{ 1164 { 1165 Addr: addrs.AbsResourceInstance{ 1166 Module: addrs.RootModuleInstance, 1167 Resource: addrs.ResourceInstance{ 1168 Resource: addrs.Resource{ 1169 Mode: addrs.ManagedResourceMode, 1170 Type: "test_instance", 1171 Name: "new_one", 1172 }, 1173 }, 1174 }, 1175 ChangeSrc: plans.ChangeSrc{ 1176 Action: plans.Create, 1177 }, 1178 }, 1179 { 1180 Addr: addrs.AbsResourceInstance{ 1181 Module: addrs.RootModuleInstance, 1182 Resource: addrs.ResourceInstance{ 1183 Resource: addrs.Resource{ 1184 Mode: addrs.ManagedResourceMode, 1185 Type: "test_instance", 1186 Name: "new_two", 1187 }, 1188 }, 1189 }, 1190 ChangeSrc: plans.ChangeSrc{ 1191 Action: plans.Create, 1192 }, 1193 }, 1194 }, 1195 run: &moduletest.Run{ 1196 Config: &configs.TestRun{}, 1197 Name: "run_block", 1198 }, 1199 want: ` 1200 Terraform was interrupted while executing main.tftest.hcl, and may not have 1201 performed the expected cleanup operations. 1202 1203 Terraform has already created the following resources from the module under 1204 test: 1205 - test_instance.one 1206 - test_instance.two 1207 1208 Terraform has already created the following resources for "setup_block" from 1209 "../setup": 1210 - test_instance.setup_one 1211 - test_instance.setup_two 1212 1213 Terraform was in the process of creating the following resources for 1214 "run_block" from the module under test, and they may not have been destroyed: 1215 - test_instance.new_one 1216 - test_instance.new_two 1217 `, 1218 }, 1219 } 1220 for name, tc := range tcs { 1221 t.Run(name, func(t *testing.T) { 1222 streams, done := terminal.StreamsForTesting(t) 1223 view := NewTest(arguments.ViewHuman, NewView(streams)) 1224 1225 file := &moduletest.File{ 1226 Name: "main.tftest.hcl", 1227 Runs: func() []*moduletest.Run { 1228 var runs []*moduletest.Run 1229 for run := range tc.states { 1230 if run != nil { 1231 runs = append(runs, run) 1232 } 1233 } 1234 return runs 1235 }(), 1236 } 1237 1238 view.FatalInterruptSummary(tc.run, file, tc.states, tc.created) 1239 actual, expected := done(t).Stderr(), tc.want 1240 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 1241 t.Errorf("expected:\n%s\nactual:\n%s\ndiff:\n%s", expected, actual, diff) 1242 } 1243 }) 1244 } 1245 } 1246 1247 func TestTestJSON_Abstract(t *testing.T) { 1248 tcs := map[string]struct { 1249 suite *moduletest.Suite 1250 want []map[string]interface{} 1251 }{ 1252 "single": { 1253 suite: &moduletest.Suite{ 1254 Files: map[string]*moduletest.File{ 1255 "main.tftest.hcl": { 1256 Runs: []*moduletest.Run{ 1257 { 1258 Name: "setup", 1259 }, 1260 }, 1261 }, 1262 }, 1263 }, 1264 want: []map[string]interface{}{ 1265 { 1266 "@level": "info", 1267 "@message": "Found 1 file and 1 run block", 1268 "@module": "terraform.ui", 1269 "test_abstract": map[string]interface{}{ 1270 "main.tftest.hcl": []interface{}{ 1271 "setup", 1272 }, 1273 }, 1274 "type": "test_abstract", 1275 }, 1276 }, 1277 }, 1278 "plural": { 1279 suite: &moduletest.Suite{ 1280 Files: map[string]*moduletest.File{ 1281 "main.tftest.hcl": { 1282 Runs: []*moduletest.Run{ 1283 { 1284 Name: "setup", 1285 }, 1286 { 1287 Name: "test", 1288 }, 1289 }, 1290 }, 1291 "other.tftest.hcl": { 1292 Runs: []*moduletest.Run{ 1293 { 1294 Name: "test", 1295 }, 1296 }, 1297 }, 1298 }, 1299 }, 1300 want: []map[string]interface{}{ 1301 { 1302 "@level": "info", 1303 "@message": "Found 2 files and 3 run blocks", 1304 "@module": "terraform.ui", 1305 "test_abstract": map[string]interface{}{ 1306 "main.tftest.hcl": []interface{}{ 1307 "setup", 1308 "test", 1309 }, 1310 "other.tftest.hcl": []interface{}{ 1311 "test", 1312 }, 1313 }, 1314 "type": "test_abstract", 1315 }, 1316 }, 1317 }, 1318 } 1319 for name, tc := range tcs { 1320 t.Run(name, func(t *testing.T) { 1321 streams, done := terminal.StreamsForTesting(t) 1322 view := NewTest(arguments.ViewJSON, NewView(streams)) 1323 1324 view.Abstract(tc.suite) 1325 testJSONViewOutputEquals(t, done(t).All(), tc.want) 1326 }) 1327 } 1328 } 1329 1330 func TestTestJSON_Conclusion(t *testing.T) { 1331 tcs := map[string]struct { 1332 suite *moduletest.Suite 1333 want []map[string]interface{} 1334 }{ 1335 "no tests": { 1336 suite: &moduletest.Suite{}, 1337 want: []map[string]interface{}{ 1338 { 1339 "@level": "info", 1340 "@message": "Executed 0 tests.", 1341 "@module": "terraform.ui", 1342 "test_summary": map[string]interface{}{ 1343 "status": "pending", 1344 "errored": 0.0, 1345 "failed": 0.0, 1346 "passed": 0.0, 1347 "skipped": 0.0, 1348 }, 1349 "type": "test_summary", 1350 }, 1351 }, 1352 }, 1353 1354 "only skipped tests": { 1355 suite: &moduletest.Suite{ 1356 Status: moduletest.Skip, 1357 Files: map[string]*moduletest.File{ 1358 "descriptive_test_name.tftest.hcl": { 1359 Name: "descriptive_test_name.tftest.hcl", 1360 Status: moduletest.Skip, 1361 Runs: []*moduletest.Run{ 1362 { 1363 Name: "test_one", 1364 Status: moduletest.Skip, 1365 }, 1366 { 1367 Name: "test_two", 1368 Status: moduletest.Skip, 1369 }, 1370 { 1371 Name: "test_three", 1372 Status: moduletest.Skip, 1373 }, 1374 }, 1375 }, 1376 "other_descriptive_test_name.tftest.hcl": { 1377 Name: "other_descriptive_test_name.tftest.hcl", 1378 Status: moduletest.Skip, 1379 Runs: []*moduletest.Run{ 1380 { 1381 Name: "test_one", 1382 Status: moduletest.Skip, 1383 }, 1384 { 1385 Name: "test_two", 1386 Status: moduletest.Skip, 1387 }, 1388 { 1389 Name: "test_three", 1390 Status: moduletest.Skip, 1391 }, 1392 }, 1393 }, 1394 }, 1395 }, 1396 want: []map[string]interface{}{ 1397 { 1398 "@level": "info", 1399 "@message": "Executed 0 tests, 6 skipped.", 1400 "@module": "terraform.ui", 1401 "test_summary": map[string]interface{}{ 1402 "status": "skip", 1403 "errored": 0.0, 1404 "failed": 0.0, 1405 "passed": 0.0, 1406 "skipped": 6.0, 1407 }, 1408 "type": "test_summary", 1409 }, 1410 }, 1411 }, 1412 1413 "only passed tests": { 1414 suite: &moduletest.Suite{ 1415 Status: moduletest.Pass, 1416 Files: map[string]*moduletest.File{ 1417 "descriptive_test_name.tftest.hcl": { 1418 Name: "descriptive_test_name.tftest.hcl", 1419 Status: moduletest.Pass, 1420 Runs: []*moduletest.Run{ 1421 { 1422 Name: "test_one", 1423 Status: moduletest.Pass, 1424 }, 1425 { 1426 Name: "test_two", 1427 Status: moduletest.Pass, 1428 }, 1429 { 1430 Name: "test_three", 1431 Status: moduletest.Pass, 1432 }, 1433 }, 1434 }, 1435 "other_descriptive_test_name.tftest.hcl": { 1436 Name: "other_descriptive_test_name.tftest.hcl", 1437 Status: moduletest.Pass, 1438 Runs: []*moduletest.Run{ 1439 { 1440 Name: "test_one", 1441 Status: moduletest.Pass, 1442 }, 1443 { 1444 Name: "test_two", 1445 Status: moduletest.Pass, 1446 }, 1447 { 1448 Name: "test_three", 1449 Status: moduletest.Pass, 1450 }, 1451 }, 1452 }, 1453 }, 1454 }, 1455 want: []map[string]interface{}{ 1456 { 1457 "@level": "info", 1458 "@message": "Success! 6 passed, 0 failed.", 1459 "@module": "terraform.ui", 1460 "test_summary": map[string]interface{}{ 1461 "status": "pass", 1462 "errored": 0.0, 1463 "failed": 0.0, 1464 "passed": 6.0, 1465 "skipped": 0.0, 1466 }, 1467 "type": "test_summary", 1468 }, 1469 }, 1470 }, 1471 1472 "passed and skipped tests": { 1473 suite: &moduletest.Suite{ 1474 Status: moduletest.Pass, 1475 Files: map[string]*moduletest.File{ 1476 "descriptive_test_name.tftest.hcl": { 1477 Name: "descriptive_test_name.tftest.hcl", 1478 Status: moduletest.Pass, 1479 Runs: []*moduletest.Run{ 1480 { 1481 Name: "test_one", 1482 Status: moduletest.Pass, 1483 }, 1484 { 1485 Name: "test_two", 1486 Status: moduletest.Skip, 1487 }, 1488 { 1489 Name: "test_three", 1490 Status: moduletest.Pass, 1491 }, 1492 }, 1493 }, 1494 "other_descriptive_test_name.tftest.hcl": { 1495 Name: "other_descriptive_test_name.tftest.hcl", 1496 Status: moduletest.Pass, 1497 Runs: []*moduletest.Run{ 1498 { 1499 Name: "test_one", 1500 Status: moduletest.Skip, 1501 }, 1502 { 1503 Name: "test_two", 1504 Status: moduletest.Pass, 1505 }, 1506 { 1507 Name: "test_three", 1508 Status: moduletest.Pass, 1509 }, 1510 }, 1511 }, 1512 }, 1513 }, 1514 want: []map[string]interface{}{ 1515 { 1516 "@level": "info", 1517 "@message": "Success! 4 passed, 0 failed, 2 skipped.", 1518 "@module": "terraform.ui", 1519 "test_summary": map[string]interface{}{ 1520 "status": "pass", 1521 "errored": 0.0, 1522 "failed": 0.0, 1523 "passed": 4.0, 1524 "skipped": 2.0, 1525 }, 1526 "type": "test_summary", 1527 }, 1528 }, 1529 }, 1530 1531 "only failed tests": { 1532 suite: &moduletest.Suite{ 1533 Status: moduletest.Fail, 1534 Files: map[string]*moduletest.File{ 1535 "descriptive_test_name.tftest.hcl": { 1536 Name: "descriptive_test_name.tftest.hcl", 1537 Status: moduletest.Fail, 1538 Runs: []*moduletest.Run{ 1539 { 1540 Name: "test_one", 1541 Status: moduletest.Fail, 1542 }, 1543 { 1544 Name: "test_two", 1545 Status: moduletest.Fail, 1546 }, 1547 { 1548 Name: "test_three", 1549 Status: moduletest.Fail, 1550 }, 1551 }, 1552 }, 1553 "other_descriptive_test_name.tftest.hcl": { 1554 Name: "other_descriptive_test_name.tftest.hcl", 1555 Status: moduletest.Fail, 1556 Runs: []*moduletest.Run{ 1557 { 1558 Name: "test_one", 1559 Status: moduletest.Fail, 1560 }, 1561 { 1562 Name: "test_two", 1563 Status: moduletest.Fail, 1564 }, 1565 { 1566 Name: "test_three", 1567 Status: moduletest.Fail, 1568 }, 1569 }, 1570 }, 1571 }, 1572 }, 1573 want: []map[string]interface{}{ 1574 { 1575 "@level": "info", 1576 "@message": "Failure! 0 passed, 6 failed.", 1577 "@module": "terraform.ui", 1578 "test_summary": map[string]interface{}{ 1579 "status": "fail", 1580 "errored": 0.0, 1581 "failed": 6.0, 1582 "passed": 0.0, 1583 "skipped": 0.0, 1584 }, 1585 "type": "test_summary", 1586 }, 1587 }, 1588 }, 1589 1590 "failed and skipped tests": { 1591 suite: &moduletest.Suite{ 1592 Status: moduletest.Fail, 1593 Files: map[string]*moduletest.File{ 1594 "descriptive_test_name.tftest.hcl": { 1595 Name: "descriptive_test_name.tftest.hcl", 1596 Status: moduletest.Fail, 1597 Runs: []*moduletest.Run{ 1598 { 1599 Name: "test_one", 1600 Status: moduletest.Fail, 1601 }, 1602 { 1603 Name: "test_two", 1604 Status: moduletest.Skip, 1605 }, 1606 { 1607 Name: "test_three", 1608 Status: moduletest.Fail, 1609 }, 1610 }, 1611 }, 1612 "other_descriptive_test_name.tftest.hcl": { 1613 Name: "other_descriptive_test_name.tftest.hcl", 1614 Status: moduletest.Fail, 1615 Runs: []*moduletest.Run{ 1616 { 1617 Name: "test_one", 1618 Status: moduletest.Fail, 1619 }, 1620 { 1621 Name: "test_two", 1622 Status: moduletest.Fail, 1623 }, 1624 { 1625 Name: "test_three", 1626 Status: moduletest.Skip, 1627 }, 1628 }, 1629 }, 1630 }, 1631 }, 1632 want: []map[string]interface{}{ 1633 { 1634 "@level": "info", 1635 "@message": "Failure! 0 passed, 4 failed, 2 skipped.", 1636 "@module": "terraform.ui", 1637 "test_summary": map[string]interface{}{ 1638 "status": "fail", 1639 "errored": 0.0, 1640 "failed": 4.0, 1641 "passed": 0.0, 1642 "skipped": 2.0, 1643 }, 1644 "type": "test_summary", 1645 }, 1646 }, 1647 }, 1648 1649 "failed, passed and skipped tests": { 1650 suite: &moduletest.Suite{ 1651 Status: moduletest.Fail, 1652 Files: map[string]*moduletest.File{ 1653 "descriptive_test_name.tftest.hcl": { 1654 Name: "descriptive_test_name.tftest.hcl", 1655 Status: moduletest.Fail, 1656 Runs: []*moduletest.Run{ 1657 { 1658 Name: "test_one", 1659 Status: moduletest.Fail, 1660 }, 1661 { 1662 Name: "test_two", 1663 Status: moduletest.Pass, 1664 }, 1665 { 1666 Name: "test_three", 1667 Status: moduletest.Skip, 1668 }, 1669 }, 1670 }, 1671 "other_descriptive_test_name.tftest.hcl": { 1672 Name: "other_descriptive_test_name.tftest.hcl", 1673 Status: moduletest.Fail, 1674 Runs: []*moduletest.Run{ 1675 { 1676 Name: "test_one", 1677 Status: moduletest.Skip, 1678 }, 1679 { 1680 Name: "test_two", 1681 Status: moduletest.Fail, 1682 }, 1683 { 1684 Name: "test_three", 1685 Status: moduletest.Pass, 1686 }, 1687 }, 1688 }, 1689 }, 1690 }, 1691 want: []map[string]interface{}{ 1692 { 1693 "@level": "info", 1694 "@message": "Failure! 2 passed, 2 failed, 2 skipped.", 1695 "@module": "terraform.ui", 1696 "test_summary": map[string]interface{}{ 1697 "status": "fail", 1698 "errored": 0.0, 1699 "failed": 2.0, 1700 "passed": 2.0, 1701 "skipped": 2.0, 1702 }, 1703 "type": "test_summary", 1704 }, 1705 }, 1706 }, 1707 1708 "failed and errored tests": { 1709 suite: &moduletest.Suite{ 1710 Status: moduletest.Error, 1711 Files: map[string]*moduletest.File{ 1712 "descriptive_test_name.tftest.hcl": { 1713 Name: "descriptive_test_name.tftest.hcl", 1714 Status: moduletest.Error, 1715 Runs: []*moduletest.Run{ 1716 { 1717 Name: "test_one", 1718 Status: moduletest.Fail, 1719 }, 1720 { 1721 Name: "test_two", 1722 Status: moduletest.Error, 1723 }, 1724 { 1725 Name: "test_three", 1726 Status: moduletest.Fail, 1727 }, 1728 }, 1729 }, 1730 "other_descriptive_test_name.tftest.hcl": { 1731 Name: "other_descriptive_test_name.tftest.hcl", 1732 Status: moduletest.Error, 1733 Runs: []*moduletest.Run{ 1734 { 1735 Name: "test_one", 1736 Status: moduletest.Fail, 1737 }, 1738 { 1739 Name: "test_two", 1740 Status: moduletest.Error, 1741 }, 1742 { 1743 Name: "test_three", 1744 Status: moduletest.Error, 1745 }, 1746 }, 1747 }, 1748 }, 1749 }, 1750 want: []map[string]interface{}{ 1751 { 1752 "@level": "info", 1753 "@message": "Failure! 0 passed, 6 failed.", 1754 "@module": "terraform.ui", 1755 "test_summary": map[string]interface{}{ 1756 "status": "error", 1757 "errored": 3.0, 1758 "failed": 3.0, 1759 "passed": 0.0, 1760 "skipped": 0.0, 1761 }, 1762 "type": "test_summary", 1763 }, 1764 }, 1765 }, 1766 1767 "failed, errored, passed, and skipped tests": { 1768 suite: &moduletest.Suite{ 1769 Status: moduletest.Error, 1770 Files: map[string]*moduletest.File{ 1771 "descriptive_test_name.tftest.hcl": { 1772 Name: "descriptive_test_name.tftest.hcl", 1773 Status: moduletest.Fail, 1774 Runs: []*moduletest.Run{ 1775 { 1776 Name: "test_one", 1777 Status: moduletest.Pass, 1778 }, 1779 { 1780 Name: "test_two", 1781 Status: moduletest.Pass, 1782 }, 1783 { 1784 Name: "test_three", 1785 Status: moduletest.Fail, 1786 }, 1787 }, 1788 }, 1789 "other_descriptive_test_name.tftest.hcl": { 1790 Name: "other_descriptive_test_name.tftest.hcl", 1791 Status: moduletest.Error, 1792 Runs: []*moduletest.Run{ 1793 { 1794 Name: "test_one", 1795 Status: moduletest.Error, 1796 }, 1797 { 1798 Name: "test_two", 1799 Status: moduletest.Skip, 1800 }, 1801 { 1802 Name: "test_three", 1803 Status: moduletest.Skip, 1804 }, 1805 }, 1806 }, 1807 }, 1808 }, 1809 want: []map[string]interface{}{ 1810 { 1811 "@level": "info", 1812 "@message": "Failure! 2 passed, 2 failed, 2 skipped.", 1813 "@module": "terraform.ui", 1814 "test_summary": map[string]interface{}{ 1815 "status": "error", 1816 "errored": 1.0, 1817 "failed": 1.0, 1818 "passed": 2.0, 1819 "skipped": 2.0, 1820 }, 1821 "type": "test_summary", 1822 }, 1823 }, 1824 }, 1825 } 1826 for name, tc := range tcs { 1827 t.Run(name, func(t *testing.T) { 1828 streams, done := terminal.StreamsForTesting(t) 1829 view := NewTest(arguments.ViewJSON, NewView(streams)) 1830 1831 view.Conclusion(tc.suite) 1832 testJSONViewOutputEquals(t, done(t).All(), tc.want) 1833 }) 1834 } 1835 } 1836 1837 func TestTestJSON_DestroySummary(t *testing.T) { 1838 tcs := map[string]struct { 1839 file *moduletest.File 1840 run *moduletest.Run 1841 state *states.State 1842 diags tfdiags.Diagnostics 1843 want []map[string]interface{} 1844 }{ 1845 "empty_state_only_warnings": { 1846 diags: tfdiags.Diagnostics{ 1847 tfdiags.Sourceless(tfdiags.Warning, "first warning", "something not very bad happened"), 1848 tfdiags.Sourceless(tfdiags.Warning, "second warning", "something not very bad happened again"), 1849 }, 1850 file: &moduletest.File{Name: "main.tftest.hcl"}, 1851 state: states.NewState(), 1852 want: []map[string]interface{}{ 1853 { 1854 "@level": "warn", 1855 "@message": "Warning: first warning", 1856 "@module": "terraform.ui", 1857 "@testfile": "main.tftest.hcl", 1858 "diagnostic": map[string]interface{}{ 1859 "detail": "something not very bad happened", 1860 "severity": "warning", 1861 "summary": "first warning", 1862 }, 1863 "type": "diagnostic", 1864 }, 1865 { 1866 "@level": "warn", 1867 "@message": "Warning: second warning", 1868 "@module": "terraform.ui", 1869 "@testfile": "main.tftest.hcl", 1870 "diagnostic": map[string]interface{}{ 1871 "detail": "something not very bad happened again", 1872 "severity": "warning", 1873 "summary": "second warning", 1874 }, 1875 "type": "diagnostic", 1876 }, 1877 }, 1878 }, 1879 "empty_state_with_errors": { 1880 diags: tfdiags.Diagnostics{ 1881 tfdiags.Sourceless(tfdiags.Warning, "first warning", "something not very bad happened"), 1882 tfdiags.Sourceless(tfdiags.Warning, "second warning", "something not very bad happened again"), 1883 tfdiags.Sourceless(tfdiags.Error, "first error", "this time it is very bad"), 1884 }, 1885 file: &moduletest.File{Name: "main.tftest.hcl"}, 1886 state: states.NewState(), 1887 want: []map[string]interface{}{ 1888 { 1889 "@level": "warn", 1890 "@message": "Warning: first warning", 1891 "@module": "terraform.ui", 1892 "@testfile": "main.tftest.hcl", 1893 "diagnostic": map[string]interface{}{ 1894 "detail": "something not very bad happened", 1895 "severity": "warning", 1896 "summary": "first warning", 1897 }, 1898 "type": "diagnostic", 1899 }, 1900 { 1901 "@level": "warn", 1902 "@message": "Warning: second warning", 1903 "@module": "terraform.ui", 1904 "@testfile": "main.tftest.hcl", 1905 "diagnostic": map[string]interface{}{ 1906 "detail": "something not very bad happened again", 1907 "severity": "warning", 1908 "summary": "second warning", 1909 }, 1910 "type": "diagnostic", 1911 }, 1912 { 1913 "@level": "error", 1914 "@message": "Error: first error", 1915 "@module": "terraform.ui", 1916 "@testfile": "main.tftest.hcl", 1917 "diagnostic": map[string]interface{}{ 1918 "detail": "this time it is very bad", 1919 "severity": "error", 1920 "summary": "first error", 1921 }, 1922 "type": "diagnostic", 1923 }, 1924 }, 1925 }, 1926 "state_from_run": { 1927 file: &moduletest.File{Name: "main.tftest.hcl"}, 1928 run: &moduletest.Run{Name: "run_block"}, 1929 state: states.BuildState(func(state *states.SyncState) { 1930 state.SetResourceInstanceCurrent( 1931 addrs.Resource{ 1932 Mode: addrs.ManagedResourceMode, 1933 Type: "test", 1934 Name: "foo", 1935 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1936 &states.ResourceInstanceObjectSrc{ 1937 Status: states.ObjectReady, 1938 }, 1939 addrs.AbsProviderConfig{ 1940 Module: addrs.RootModule, 1941 Provider: addrs.NewDefaultProvider("test"), 1942 }) 1943 }), 1944 want: []map[string]interface{}{ 1945 { 1946 "@level": "error", 1947 "@message": "Terraform left some resources in state after executing main.tftest.hcl/run_block, they need to be cleaned up manually.", 1948 "@module": "terraform.ui", 1949 "@testfile": "main.tftest.hcl", 1950 "@testrun": "run_block", 1951 "test_cleanup": map[string]interface{}{ 1952 "failed_resources": []interface{}{ 1953 map[string]interface{}{ 1954 "instance": "test.foo", 1955 }, 1956 }, 1957 }, 1958 "type": "test_cleanup", 1959 }, 1960 }, 1961 }, 1962 "state_only_warnings": { 1963 diags: tfdiags.Diagnostics{ 1964 tfdiags.Sourceless(tfdiags.Warning, "first warning", "something not very bad happened"), 1965 tfdiags.Sourceless(tfdiags.Warning, "second warning", "something not very bad happened again"), 1966 }, 1967 file: &moduletest.File{Name: "main.tftest.hcl"}, 1968 state: states.BuildState(func(state *states.SyncState) { 1969 state.SetResourceInstanceCurrent( 1970 addrs.Resource{ 1971 Mode: addrs.ManagedResourceMode, 1972 Type: "test", 1973 Name: "foo", 1974 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1975 &states.ResourceInstanceObjectSrc{ 1976 Status: states.ObjectReady, 1977 }, 1978 addrs.AbsProviderConfig{ 1979 Module: addrs.RootModule, 1980 Provider: addrs.NewDefaultProvider("test"), 1981 }) 1982 state.SetResourceInstanceCurrent( 1983 addrs.Resource{ 1984 Mode: addrs.ManagedResourceMode, 1985 Type: "test", 1986 Name: "bar", 1987 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 1988 &states.ResourceInstanceObjectSrc{ 1989 Status: states.ObjectReady, 1990 }, 1991 addrs.AbsProviderConfig{ 1992 Module: addrs.RootModule, 1993 Provider: addrs.NewDefaultProvider("test"), 1994 }) 1995 state.SetResourceInstanceDeposed( 1996 addrs.Resource{ 1997 Mode: addrs.ManagedResourceMode, 1998 Type: "test", 1999 Name: "bar", 2000 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 2001 "0fcb640a", 2002 &states.ResourceInstanceObjectSrc{ 2003 Status: states.ObjectReady, 2004 }, 2005 addrs.AbsProviderConfig{ 2006 Module: addrs.RootModule, 2007 Provider: addrs.NewDefaultProvider("test"), 2008 }) 2009 }), 2010 want: []map[string]interface{}{ 2011 { 2012 "@level": "error", 2013 "@message": "Terraform left some resources in state after executing main.tftest.hcl, they need to be cleaned up manually.", 2014 "@module": "terraform.ui", 2015 "@testfile": "main.tftest.hcl", 2016 "test_cleanup": map[string]interface{}{ 2017 "failed_resources": []interface{}{ 2018 map[string]interface{}{ 2019 "instance": "test.bar", 2020 }, 2021 map[string]interface{}{ 2022 "instance": "test.bar", 2023 "deposed_key": "0fcb640a", 2024 }, 2025 map[string]interface{}{ 2026 "instance": "test.foo", 2027 }, 2028 }, 2029 }, 2030 "type": "test_cleanup", 2031 }, 2032 { 2033 "@level": "warn", 2034 "@message": "Warning: first warning", 2035 "@module": "terraform.ui", 2036 "@testfile": "main.tftest.hcl", 2037 "diagnostic": map[string]interface{}{ 2038 "detail": "something not very bad happened", 2039 "severity": "warning", 2040 "summary": "first warning", 2041 }, 2042 "type": "diagnostic", 2043 }, 2044 { 2045 "@level": "warn", 2046 "@message": "Warning: second warning", 2047 "@module": "terraform.ui", 2048 "@testfile": "main.tftest.hcl", 2049 "diagnostic": map[string]interface{}{ 2050 "detail": "something not very bad happened again", 2051 "severity": "warning", 2052 "summary": "second warning", 2053 }, 2054 "type": "diagnostic", 2055 }, 2056 }, 2057 }, 2058 "state_with_errors": { 2059 diags: tfdiags.Diagnostics{ 2060 tfdiags.Sourceless(tfdiags.Warning, "first warning", "something not very bad happened"), 2061 tfdiags.Sourceless(tfdiags.Warning, "second warning", "something not very bad happened again"), 2062 tfdiags.Sourceless(tfdiags.Error, "first error", "this time it is very bad"), 2063 }, 2064 file: &moduletest.File{Name: "main.tftest.hcl"}, 2065 state: states.BuildState(func(state *states.SyncState) { 2066 state.SetResourceInstanceCurrent( 2067 addrs.Resource{ 2068 Mode: addrs.ManagedResourceMode, 2069 Type: "test", 2070 Name: "foo", 2071 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 2072 &states.ResourceInstanceObjectSrc{ 2073 Status: states.ObjectReady, 2074 }, 2075 addrs.AbsProviderConfig{ 2076 Module: addrs.RootModule, 2077 Provider: addrs.NewDefaultProvider("test"), 2078 }) 2079 state.SetResourceInstanceCurrent( 2080 addrs.Resource{ 2081 Mode: addrs.ManagedResourceMode, 2082 Type: "test", 2083 Name: "bar", 2084 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 2085 &states.ResourceInstanceObjectSrc{ 2086 Status: states.ObjectReady, 2087 }, 2088 addrs.AbsProviderConfig{ 2089 Module: addrs.RootModule, 2090 Provider: addrs.NewDefaultProvider("test"), 2091 }) 2092 state.SetResourceInstanceDeposed( 2093 addrs.Resource{ 2094 Mode: addrs.ManagedResourceMode, 2095 Type: "test", 2096 Name: "bar", 2097 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 2098 "0fcb640a", 2099 &states.ResourceInstanceObjectSrc{ 2100 Status: states.ObjectReady, 2101 }, 2102 addrs.AbsProviderConfig{ 2103 Module: addrs.RootModule, 2104 Provider: addrs.NewDefaultProvider("test"), 2105 }) 2106 }), 2107 want: []map[string]interface{}{ 2108 { 2109 "@level": "error", 2110 "@message": "Terraform left some resources in state after executing main.tftest.hcl, they need to be cleaned up manually.", 2111 "@module": "terraform.ui", 2112 "@testfile": "main.tftest.hcl", 2113 "test_cleanup": map[string]interface{}{ 2114 "failed_resources": []interface{}{ 2115 map[string]interface{}{ 2116 "instance": "test.bar", 2117 }, 2118 map[string]interface{}{ 2119 "instance": "test.bar", 2120 "deposed_key": "0fcb640a", 2121 }, 2122 map[string]interface{}{ 2123 "instance": "test.foo", 2124 }, 2125 }, 2126 }, 2127 "type": "test_cleanup", 2128 }, 2129 { 2130 "@level": "warn", 2131 "@message": "Warning: first warning", 2132 "@module": "terraform.ui", 2133 "@testfile": "main.tftest.hcl", 2134 "diagnostic": map[string]interface{}{ 2135 "detail": "something not very bad happened", 2136 "severity": "warning", 2137 "summary": "first warning", 2138 }, 2139 "type": "diagnostic", 2140 }, 2141 { 2142 "@level": "warn", 2143 "@message": "Warning: second warning", 2144 "@module": "terraform.ui", 2145 "@testfile": "main.tftest.hcl", 2146 "diagnostic": map[string]interface{}{ 2147 "detail": "something not very bad happened again", 2148 "severity": "warning", 2149 "summary": "second warning", 2150 }, 2151 "type": "diagnostic", 2152 }, 2153 { 2154 "@level": "error", 2155 "@message": "Error: first error", 2156 "@module": "terraform.ui", 2157 "@testfile": "main.tftest.hcl", 2158 "diagnostic": map[string]interface{}{ 2159 "detail": "this time it is very bad", 2160 "severity": "error", 2161 "summary": "first error", 2162 }, 2163 "type": "diagnostic", 2164 }, 2165 }, 2166 }, 2167 } 2168 for name, tc := range tcs { 2169 t.Run(name, func(t *testing.T) { 2170 streams, done := terminal.StreamsForTesting(t) 2171 view := NewTest(arguments.ViewJSON, NewView(streams)) 2172 2173 view.DestroySummary(tc.diags, tc.run, tc.file, tc.state) 2174 testJSONViewOutputEquals(t, done(t).All(), tc.want) 2175 }) 2176 } 2177 } 2178 2179 func TestTestJSON_File(t *testing.T) { 2180 tcs := map[string]struct { 2181 file *moduletest.File 2182 want []map[string]interface{} 2183 }{ 2184 "pass": { 2185 file: &moduletest.File{Name: "main.tf", Status: moduletest.Pass}, 2186 want: []map[string]interface{}{ 2187 { 2188 "@level": "info", 2189 "@message": "main.tf... pass", 2190 "@module": "terraform.ui", 2191 "@testfile": "main.tf", 2192 "test_file": map[string]interface{}{ 2193 "path": "main.tf", 2194 "status": "pass", 2195 }, 2196 "type": "test_file", 2197 }, 2198 }, 2199 }, 2200 2201 "pending": { 2202 file: &moduletest.File{Name: "main.tf", Status: moduletest.Pending}, 2203 want: []map[string]interface{}{ 2204 { 2205 "@level": "info", 2206 "@message": "main.tf... pending", 2207 "@module": "terraform.ui", 2208 "@testfile": "main.tf", 2209 "test_file": map[string]interface{}{ 2210 "path": "main.tf", 2211 "status": "pending", 2212 }, 2213 "type": "test_file", 2214 }, 2215 }, 2216 }, 2217 2218 "skip": { 2219 file: &moduletest.File{Name: "main.tf", Status: moduletest.Skip}, 2220 want: []map[string]interface{}{ 2221 { 2222 "@level": "info", 2223 "@message": "main.tf... skip", 2224 "@module": "terraform.ui", 2225 "@testfile": "main.tf", 2226 "test_file": map[string]interface{}{ 2227 "path": "main.tf", 2228 "status": "skip", 2229 }, 2230 "type": "test_file", 2231 }, 2232 }, 2233 }, 2234 2235 "fail": { 2236 file: &moduletest.File{Name: "main.tf", Status: moduletest.Fail}, 2237 want: []map[string]interface{}{ 2238 { 2239 "@level": "info", 2240 "@message": "main.tf... fail", 2241 "@module": "terraform.ui", 2242 "@testfile": "main.tf", 2243 "test_file": map[string]interface{}{ 2244 "path": "main.tf", 2245 "status": "fail", 2246 }, 2247 "type": "test_file", 2248 }, 2249 }, 2250 }, 2251 2252 "error": { 2253 file: &moduletest.File{Name: "main.tf", Status: moduletest.Error}, 2254 want: []map[string]interface{}{ 2255 { 2256 "@level": "info", 2257 "@message": "main.tf... fail", 2258 "@module": "terraform.ui", 2259 "@testfile": "main.tf", 2260 "test_file": map[string]interface{}{ 2261 "path": "main.tf", 2262 "status": "error", 2263 }, 2264 "type": "test_file", 2265 }, 2266 }, 2267 }, 2268 } 2269 for name, tc := range tcs { 2270 t.Run(name, func(t *testing.T) { 2271 streams, done := terminal.StreamsForTesting(t) 2272 view := NewTest(arguments.ViewJSON, NewView(streams)) 2273 2274 view.File(tc.file) 2275 testJSONViewOutputEquals(t, done(t).All(), tc.want) 2276 }) 2277 } 2278 } 2279 2280 func TestTestJSON_Run(t *testing.T) { 2281 tcs := map[string]struct { 2282 run *moduletest.Run 2283 want []map[string]interface{} 2284 }{ 2285 "pass": { 2286 run: &moduletest.Run{Name: "run_block", Status: moduletest.Pass}, 2287 want: []map[string]interface{}{ 2288 { 2289 "@level": "info", 2290 "@message": " \"run_block\"... pass", 2291 "@module": "terraform.ui", 2292 "@testfile": "main.tftest.hcl", 2293 "@testrun": "run_block", 2294 "test_run": map[string]interface{}{ 2295 "path": "main.tftest.hcl", 2296 "run": "run_block", 2297 "status": "pass", 2298 }, 2299 "type": "test_run", 2300 }, 2301 }, 2302 }, 2303 2304 "pass_with_diags": { 2305 run: &moduletest.Run{ 2306 Name: "run_block", 2307 Status: moduletest.Pass, 2308 Diagnostics: tfdiags.Diagnostics{tfdiags.Sourceless(tfdiags.Warning, "a warning occurred", "some warning happened during this test")}, 2309 }, 2310 want: []map[string]interface{}{ 2311 { 2312 "@level": "info", 2313 "@message": " \"run_block\"... pass", 2314 "@module": "terraform.ui", 2315 "@testfile": "main.tftest.hcl", 2316 "@testrun": "run_block", 2317 "test_run": map[string]interface{}{ 2318 "path": "main.tftest.hcl", 2319 "run": "run_block", 2320 "status": "pass", 2321 }, 2322 "type": "test_run", 2323 }, 2324 { 2325 "@level": "warn", 2326 "@message": "Warning: a warning occurred", 2327 "@module": "terraform.ui", 2328 "@testfile": "main.tftest.hcl", 2329 "@testrun": "run_block", 2330 "diagnostic": map[string]interface{}{ 2331 "detail": "some warning happened during this test", 2332 "severity": "warning", 2333 "summary": "a warning occurred", 2334 }, 2335 "type": "diagnostic", 2336 }, 2337 }, 2338 }, 2339 2340 "pending": { 2341 run: &moduletest.Run{Name: "run_block", Status: moduletest.Pending}, 2342 want: []map[string]interface{}{ 2343 { 2344 "@level": "info", 2345 "@message": " \"run_block\"... pending", 2346 "@module": "terraform.ui", 2347 "@testfile": "main.tftest.hcl", 2348 "@testrun": "run_block", 2349 "test_run": map[string]interface{}{ 2350 "path": "main.tftest.hcl", 2351 "run": "run_block", 2352 "status": "pending", 2353 }, 2354 "type": "test_run", 2355 }, 2356 }, 2357 }, 2358 2359 "skip": { 2360 run: &moduletest.Run{Name: "run_block", Status: moduletest.Skip}, 2361 want: []map[string]interface{}{ 2362 { 2363 "@level": "info", 2364 "@message": " \"run_block\"... skip", 2365 "@module": "terraform.ui", 2366 "@testfile": "main.tftest.hcl", 2367 "@testrun": "run_block", 2368 "test_run": map[string]interface{}{ 2369 "path": "main.tftest.hcl", 2370 "run": "run_block", 2371 "status": "skip", 2372 }, 2373 "type": "test_run", 2374 }, 2375 }, 2376 }, 2377 2378 "fail": { 2379 run: &moduletest.Run{Name: "run_block", Status: moduletest.Fail}, 2380 want: []map[string]interface{}{ 2381 { 2382 "@level": "info", 2383 "@message": " \"run_block\"... fail", 2384 "@module": "terraform.ui", 2385 "@testfile": "main.tftest.hcl", 2386 "@testrun": "run_block", 2387 "test_run": map[string]interface{}{ 2388 "path": "main.tftest.hcl", 2389 "run": "run_block", 2390 "status": "fail", 2391 }, 2392 "type": "test_run", 2393 }, 2394 }, 2395 }, 2396 2397 "fail_with_diags": { 2398 run: &moduletest.Run{ 2399 Name: "run_block", 2400 Status: moduletest.Fail, 2401 Diagnostics: tfdiags.Diagnostics{ 2402 tfdiags.Sourceless(tfdiags.Error, "a comparison failed", "details details details"), 2403 tfdiags.Sourceless(tfdiags.Error, "a second comparison failed", "other details"), 2404 }, 2405 }, 2406 want: []map[string]interface{}{ 2407 { 2408 "@level": "info", 2409 "@message": " \"run_block\"... fail", 2410 "@module": "terraform.ui", 2411 "@testfile": "main.tftest.hcl", 2412 "@testrun": "run_block", 2413 "test_run": map[string]interface{}{ 2414 "path": "main.tftest.hcl", 2415 "run": "run_block", 2416 "status": "fail", 2417 }, 2418 "type": "test_run", 2419 }, 2420 { 2421 "@level": "error", 2422 "@message": "Error: a comparison failed", 2423 "@module": "terraform.ui", 2424 "@testfile": "main.tftest.hcl", 2425 "@testrun": "run_block", 2426 "diagnostic": map[string]interface{}{ 2427 "detail": "details details details", 2428 "severity": "error", 2429 "summary": "a comparison failed", 2430 }, 2431 "type": "diagnostic", 2432 }, 2433 { 2434 "@level": "error", 2435 "@message": "Error: a second comparison failed", 2436 "@module": "terraform.ui", 2437 "@testfile": "main.tftest.hcl", 2438 "@testrun": "run_block", 2439 "diagnostic": map[string]interface{}{ 2440 "detail": "other details", 2441 "severity": "error", 2442 "summary": "a second comparison failed", 2443 }, 2444 "type": "diagnostic", 2445 }, 2446 }, 2447 }, 2448 2449 "error": { 2450 run: &moduletest.Run{Name: "run_block", Status: moduletest.Error}, 2451 want: []map[string]interface{}{ 2452 { 2453 "@level": "info", 2454 "@message": " \"run_block\"... fail", 2455 "@module": "terraform.ui", 2456 "@testfile": "main.tftest.hcl", 2457 "@testrun": "run_block", 2458 "test_run": map[string]interface{}{ 2459 "path": "main.tftest.hcl", 2460 "run": "run_block", 2461 "status": "error", 2462 }, 2463 "type": "test_run", 2464 }, 2465 }, 2466 }, 2467 2468 "error_with_diags": { 2469 run: &moduletest.Run{ 2470 Name: "run_block", 2471 Status: moduletest.Error, 2472 Diagnostics: tfdiags.Diagnostics{tfdiags.Sourceless(tfdiags.Error, "an error occurred", "something bad happened during this test")}, 2473 }, 2474 want: []map[string]interface{}{ 2475 { 2476 "@level": "info", 2477 "@message": " \"run_block\"... fail", 2478 "@module": "terraform.ui", 2479 "@testfile": "main.tftest.hcl", 2480 "@testrun": "run_block", 2481 "test_run": map[string]interface{}{ 2482 "path": "main.tftest.hcl", 2483 "run": "run_block", 2484 "status": "error", 2485 }, 2486 "type": "test_run", 2487 }, 2488 { 2489 "@level": "error", 2490 "@message": "Error: an error occurred", 2491 "@module": "terraform.ui", 2492 "@testfile": "main.tftest.hcl", 2493 "@testrun": "run_block", 2494 "diagnostic": map[string]interface{}{ 2495 "detail": "something bad happened during this test", 2496 "severity": "error", 2497 "summary": "an error occurred", 2498 }, 2499 "type": "diagnostic", 2500 }, 2501 }, 2502 }, 2503 2504 "verbose_plan": { 2505 run: &moduletest.Run{ 2506 Name: "run_block", 2507 Status: moduletest.Pass, 2508 Config: &configs.TestRun{ 2509 Command: configs.PlanTestCommand, 2510 }, 2511 Verbose: &moduletest.Verbose{ 2512 Plan: &plans.Plan{ 2513 Changes: &plans.Changes{ 2514 Resources: []*plans.ResourceInstanceChangeSrc{ 2515 { 2516 Addr: addrs.AbsResourceInstance{ 2517 Module: addrs.RootModuleInstance, 2518 Resource: addrs.ResourceInstance{ 2519 Resource: addrs.Resource{ 2520 Mode: addrs.ManagedResourceMode, 2521 Type: "test_resource", 2522 Name: "creating", 2523 }, 2524 }, 2525 }, 2526 PrevRunAddr: addrs.AbsResourceInstance{ 2527 Module: addrs.RootModuleInstance, 2528 Resource: addrs.ResourceInstance{ 2529 Resource: addrs.Resource{ 2530 Mode: addrs.ManagedResourceMode, 2531 Type: "test_resource", 2532 Name: "creating", 2533 }, 2534 }, 2535 }, 2536 ProviderAddr: addrs.AbsProviderConfig{ 2537 Module: addrs.RootModule, 2538 Provider: addrs.Provider{ 2539 Hostname: addrs.DefaultProviderRegistryHost, 2540 Namespace: "hashicorp", 2541 Type: "test", 2542 }, 2543 }, 2544 ChangeSrc: plans.ChangeSrc{ 2545 Action: plans.Create, 2546 After: dynamicValue( 2547 t, 2548 cty.ObjectVal(map[string]cty.Value{ 2549 "value": cty.StringVal("foobar"), 2550 }), 2551 cty.Object(map[string]cty.Type{ 2552 "value": cty.String, 2553 })), 2554 }, 2555 }, 2556 }, 2557 }, 2558 }, 2559 State: states.NewState(), // empty state 2560 Config: &configs.Config{ 2561 Module: &configs.Module{ 2562 ProviderRequirements: &configs.RequiredProviders{}, 2563 }, 2564 }, 2565 Providers: map[addrs.Provider]providers.ProviderSchema{ 2566 addrs.Provider{ 2567 Hostname: addrs.DefaultProviderRegistryHost, 2568 Namespace: "hashicorp", 2569 Type: "test", 2570 }: { 2571 ResourceTypes: map[string]providers.Schema{ 2572 "test_resource": { 2573 Block: &configschema.Block{ 2574 Attributes: map[string]*configschema.Attribute{ 2575 "value": { 2576 Type: cty.String, 2577 }, 2578 }, 2579 }, 2580 }, 2581 }, 2582 }, 2583 }, 2584 }, 2585 }, 2586 want: []map[string]interface{}{ 2587 { 2588 "@level": "info", 2589 "@message": " \"run_block\"... pass", 2590 "@module": "terraform.ui", 2591 "@testfile": "main.tftest.hcl", 2592 "@testrun": "run_block", 2593 "test_run": map[string]interface{}{ 2594 "path": "main.tftest.hcl", 2595 "run": "run_block", 2596 "status": "pass", 2597 }, 2598 "type": "test_run", 2599 }, 2600 { 2601 "@level": "info", 2602 "@message": "-verbose flag enabled, printing plan", 2603 "@module": "terraform.ui", 2604 "@testfile": "main.tftest.hcl", 2605 "@testrun": "run_block", 2606 "test_plan": map[string]interface{}{ 2607 "configuration": map[string]interface{}{ 2608 "root_module": map[string]interface{}{}, 2609 }, 2610 "errored": false, 2611 "planned_values": map[string]interface{}{ 2612 "root_module": map[string]interface{}{ 2613 "resources": []interface{}{ 2614 map[string]interface{}{ 2615 "address": "test_resource.creating", 2616 "mode": "managed", 2617 "name": "creating", 2618 "provider_name": "registry.terraform.io/hashicorp/test", 2619 "schema_version": 0.0, 2620 "sensitive_values": map[string]interface{}{}, 2621 "type": "test_resource", 2622 "values": map[string]interface{}{ 2623 "value": "foobar", 2624 }, 2625 }, 2626 }, 2627 }, 2628 }, 2629 "resource_changes": []interface{}{ 2630 map[string]interface{}{ 2631 "address": "test_resource.creating", 2632 "change": map[string]interface{}{ 2633 "actions": []interface{}{"create"}, 2634 "after": map[string]interface{}{ 2635 "value": "foobar", 2636 }, 2637 "after_sensitive": map[string]interface{}{}, 2638 "after_unknown": map[string]interface{}{}, 2639 "before": nil, 2640 "before_sensitive": false, 2641 }, 2642 "mode": "managed", 2643 "name": "creating", 2644 "provider_name": "registry.terraform.io/hashicorp/test", 2645 "type": "test_resource", 2646 }, 2647 }, 2648 }, 2649 "type": "test_plan", 2650 }, 2651 }, 2652 }, 2653 "verbose_apply": { 2654 run: &moduletest.Run{ 2655 Name: "run_block", 2656 Status: moduletest.Pass, 2657 Config: &configs.TestRun{ 2658 Command: configs.ApplyTestCommand, 2659 }, 2660 Verbose: &moduletest.Verbose{ 2661 Plan: &plans.Plan{}, // empty plan 2662 State: states.BuildState(func(state *states.SyncState) { 2663 state.SetResourceInstanceCurrent( 2664 addrs.AbsResourceInstance{ 2665 Module: addrs.RootModuleInstance, 2666 Resource: addrs.ResourceInstance{ 2667 Resource: addrs.Resource{ 2668 Mode: addrs.ManagedResourceMode, 2669 Type: "test_resource", 2670 Name: "creating", 2671 }, 2672 }, 2673 }, 2674 &states.ResourceInstanceObjectSrc{ 2675 AttrsJSON: []byte(`{"value":"foobar"}`), 2676 }, 2677 addrs.AbsProviderConfig{ 2678 Module: addrs.RootModule, 2679 Provider: addrs.Provider{ 2680 Hostname: addrs.DefaultProviderRegistryHost, 2681 Namespace: "hashicorp", 2682 Type: "test", 2683 }, 2684 }) 2685 }), 2686 Config: &configs.Config{ 2687 Module: &configs.Module{}, 2688 }, 2689 Providers: map[addrs.Provider]providers.ProviderSchema{ 2690 addrs.Provider{ 2691 Hostname: addrs.DefaultProviderRegistryHost, 2692 Namespace: "hashicorp", 2693 Type: "test", 2694 }: { 2695 ResourceTypes: map[string]providers.Schema{ 2696 "test_resource": { 2697 Block: &configschema.Block{ 2698 Attributes: map[string]*configschema.Attribute{ 2699 "value": { 2700 Type: cty.String, 2701 }, 2702 }, 2703 }, 2704 }, 2705 }, 2706 }, 2707 }, 2708 }, 2709 }, 2710 want: []map[string]interface{}{ 2711 { 2712 "@level": "info", 2713 "@message": " \"run_block\"... pass", 2714 "@module": "terraform.ui", 2715 "@testfile": "main.tftest.hcl", 2716 "@testrun": "run_block", 2717 "test_run": map[string]interface{}{ 2718 "path": "main.tftest.hcl", 2719 "run": "run_block", 2720 "status": "pass", 2721 }, 2722 "type": "test_run", 2723 }, 2724 { 2725 "@level": "info", 2726 "@message": "-verbose flag enabled, printing state", 2727 "@module": "terraform.ui", 2728 "@testfile": "main.tftest.hcl", 2729 "@testrun": "run_block", 2730 "test_state": map[string]interface{}{ 2731 "values": map[string]interface{}{ 2732 "root_module": map[string]interface{}{ 2733 "resources": []interface{}{ 2734 map[string]interface{}{ 2735 "address": "test_resource.creating", 2736 "mode": "managed", 2737 "name": "creating", 2738 "provider_name": "registry.terraform.io/hashicorp/test", 2739 "schema_version": 0.0, 2740 "sensitive_values": map[string]interface{}{}, 2741 "type": "test_resource", 2742 "values": map[string]interface{}{ 2743 "value": "foobar", 2744 }, 2745 }, 2746 }, 2747 }, 2748 }, 2749 }, 2750 "type": "test_state", 2751 }, 2752 }, 2753 }, 2754 } 2755 for name, tc := range tcs { 2756 t.Run(name, func(t *testing.T) { 2757 streams, done := terminal.StreamsForTesting(t) 2758 view := NewTest(arguments.ViewJSON, NewView(streams)) 2759 2760 file := &moduletest.File{Name: "main.tftest.hcl"} 2761 2762 view.Run(tc.run, file) 2763 testJSONViewOutputEquals(t, done(t).All(), tc.want, cmp.FilterPath(func(path cmp.Path) bool { 2764 return strings.Contains(path.Last().String(), "version") || strings.Contains(path.Last().String(), "timestamp") 2765 }, cmp.Ignore())) 2766 }) 2767 } 2768 } 2769 2770 func TestTestJSON_FatalInterruptSummary(t *testing.T) { 2771 tcs := map[string]struct { 2772 states map[*moduletest.Run]*states.State 2773 changes []*plans.ResourceInstanceChangeSrc 2774 want []map[string]interface{} 2775 }{ 2776 "no_state_only_plan": { 2777 states: make(map[*moduletest.Run]*states.State), 2778 changes: []*plans.ResourceInstanceChangeSrc{ 2779 { 2780 Addr: addrs.AbsResourceInstance{ 2781 Module: addrs.RootModuleInstance, 2782 Resource: addrs.ResourceInstance{ 2783 Resource: addrs.Resource{ 2784 Mode: addrs.ManagedResourceMode, 2785 Type: "test_instance", 2786 Name: "one", 2787 }, 2788 }, 2789 }, 2790 ChangeSrc: plans.ChangeSrc{ 2791 Action: plans.Create, 2792 }, 2793 }, 2794 { 2795 Addr: addrs.AbsResourceInstance{ 2796 Module: addrs.RootModuleInstance, 2797 Resource: addrs.ResourceInstance{ 2798 Resource: addrs.Resource{ 2799 Mode: addrs.ManagedResourceMode, 2800 Type: "test_instance", 2801 Name: "two", 2802 }, 2803 }, 2804 }, 2805 ChangeSrc: plans.ChangeSrc{ 2806 Action: plans.Create, 2807 }, 2808 }, 2809 }, 2810 want: []map[string]interface{}{ 2811 { 2812 "@level": "error", 2813 "@message": "Terraform was interrupted during test execution, and may not have performed the expected cleanup operations.", 2814 "@module": "terraform.ui", 2815 "@testfile": "main.tftest.hcl", 2816 "test_interrupt": map[string]interface{}{ 2817 "planned": []interface{}{ 2818 "test_instance.one", 2819 "test_instance.two", 2820 }, 2821 }, 2822 "type": "test_interrupt", 2823 }, 2824 }, 2825 }, 2826 "file_state_no_plan": { 2827 states: map[*moduletest.Run]*states.State{ 2828 nil: states.BuildState(func(state *states.SyncState) { 2829 state.SetResourceInstanceCurrent( 2830 addrs.AbsResourceInstance{ 2831 Module: addrs.RootModuleInstance, 2832 Resource: addrs.ResourceInstance{ 2833 Resource: addrs.Resource{ 2834 Mode: addrs.ManagedResourceMode, 2835 Type: "test_instance", 2836 Name: "one", 2837 }, 2838 }, 2839 }, 2840 &states.ResourceInstanceObjectSrc{}, 2841 addrs.AbsProviderConfig{}) 2842 2843 state.SetResourceInstanceCurrent( 2844 addrs.AbsResourceInstance{ 2845 Module: addrs.RootModuleInstance, 2846 Resource: addrs.ResourceInstance{ 2847 Resource: addrs.Resource{ 2848 Mode: addrs.ManagedResourceMode, 2849 Type: "test_instance", 2850 Name: "two", 2851 }, 2852 }, 2853 }, 2854 &states.ResourceInstanceObjectSrc{}, 2855 addrs.AbsProviderConfig{}) 2856 }), 2857 }, 2858 changes: nil, 2859 want: []map[string]interface{}{ 2860 { 2861 "@level": "error", 2862 "@message": "Terraform was interrupted during test execution, and may not have performed the expected cleanup operations.", 2863 "@module": "terraform.ui", 2864 "@testfile": "main.tftest.hcl", 2865 "test_interrupt": map[string]interface{}{ 2866 "state": []interface{}{ 2867 map[string]interface{}{ 2868 "instance": "test_instance.one", 2869 }, 2870 map[string]interface{}{ 2871 "instance": "test_instance.two", 2872 }, 2873 }, 2874 }, 2875 "type": "test_interrupt", 2876 }, 2877 }, 2878 }, 2879 "run_states_no_plan": { 2880 states: map[*moduletest.Run]*states.State{ 2881 &moduletest.Run{Name: "setup_block"}: states.BuildState(func(state *states.SyncState) { 2882 state.SetResourceInstanceCurrent( 2883 addrs.AbsResourceInstance{ 2884 Module: addrs.RootModuleInstance, 2885 Resource: addrs.ResourceInstance{ 2886 Resource: addrs.Resource{ 2887 Mode: addrs.ManagedResourceMode, 2888 Type: "test_instance", 2889 Name: "one", 2890 }, 2891 }, 2892 }, 2893 &states.ResourceInstanceObjectSrc{}, 2894 addrs.AbsProviderConfig{}) 2895 2896 state.SetResourceInstanceCurrent( 2897 addrs.AbsResourceInstance{ 2898 Module: addrs.RootModuleInstance, 2899 Resource: addrs.ResourceInstance{ 2900 Resource: addrs.Resource{ 2901 Mode: addrs.ManagedResourceMode, 2902 Type: "test_instance", 2903 Name: "two", 2904 }, 2905 }, 2906 }, 2907 &states.ResourceInstanceObjectSrc{}, 2908 addrs.AbsProviderConfig{}) 2909 }), 2910 }, 2911 changes: nil, 2912 want: []map[string]interface{}{ 2913 { 2914 "@level": "error", 2915 "@message": "Terraform was interrupted during test execution, and may not have performed the expected cleanup operations.", 2916 "@module": "terraform.ui", 2917 "@testfile": "main.tftest.hcl", 2918 "test_interrupt": map[string]interface{}{ 2919 "states": map[string]interface{}{ 2920 "setup_block": []interface{}{ 2921 map[string]interface{}{ 2922 "instance": "test_instance.one", 2923 }, 2924 map[string]interface{}{ 2925 "instance": "test_instance.two", 2926 }, 2927 }, 2928 }, 2929 }, 2930 "type": "test_interrupt", 2931 }, 2932 }, 2933 }, 2934 "all_states_with_plan": { 2935 states: map[*moduletest.Run]*states.State{ 2936 &moduletest.Run{Name: "setup_block"}: states.BuildState(func(state *states.SyncState) { 2937 state.SetResourceInstanceCurrent( 2938 addrs.AbsResourceInstance{ 2939 Module: addrs.RootModuleInstance, 2940 Resource: addrs.ResourceInstance{ 2941 Resource: addrs.Resource{ 2942 Mode: addrs.ManagedResourceMode, 2943 Type: "test_instance", 2944 Name: "setup_one", 2945 }, 2946 }, 2947 }, 2948 &states.ResourceInstanceObjectSrc{}, 2949 addrs.AbsProviderConfig{}) 2950 2951 state.SetResourceInstanceCurrent( 2952 addrs.AbsResourceInstance{ 2953 Module: addrs.RootModuleInstance, 2954 Resource: addrs.ResourceInstance{ 2955 Resource: addrs.Resource{ 2956 Mode: addrs.ManagedResourceMode, 2957 Type: "test_instance", 2958 Name: "setup_two", 2959 }, 2960 }, 2961 }, 2962 &states.ResourceInstanceObjectSrc{}, 2963 addrs.AbsProviderConfig{}) 2964 }), 2965 nil: states.BuildState(func(state *states.SyncState) { 2966 state.SetResourceInstanceCurrent( 2967 addrs.AbsResourceInstance{ 2968 Module: addrs.RootModuleInstance, 2969 Resource: addrs.ResourceInstance{ 2970 Resource: addrs.Resource{ 2971 Mode: addrs.ManagedResourceMode, 2972 Type: "test_instance", 2973 Name: "one", 2974 }, 2975 }, 2976 }, 2977 &states.ResourceInstanceObjectSrc{}, 2978 addrs.AbsProviderConfig{}) 2979 2980 state.SetResourceInstanceCurrent( 2981 addrs.AbsResourceInstance{ 2982 Module: addrs.RootModuleInstance, 2983 Resource: addrs.ResourceInstance{ 2984 Resource: addrs.Resource{ 2985 Mode: addrs.ManagedResourceMode, 2986 Type: "test_instance", 2987 Name: "two", 2988 }, 2989 }, 2990 }, 2991 &states.ResourceInstanceObjectSrc{}, 2992 addrs.AbsProviderConfig{}) 2993 }), 2994 }, 2995 changes: []*plans.ResourceInstanceChangeSrc{ 2996 { 2997 Addr: addrs.AbsResourceInstance{ 2998 Module: addrs.RootModuleInstance, 2999 Resource: addrs.ResourceInstance{ 3000 Resource: addrs.Resource{ 3001 Mode: addrs.ManagedResourceMode, 3002 Type: "test_instance", 3003 Name: "new_one", 3004 }, 3005 }, 3006 }, 3007 ChangeSrc: plans.ChangeSrc{ 3008 Action: plans.Create, 3009 }, 3010 }, 3011 { 3012 Addr: addrs.AbsResourceInstance{ 3013 Module: addrs.RootModuleInstance, 3014 Resource: addrs.ResourceInstance{ 3015 Resource: addrs.Resource{ 3016 Mode: addrs.ManagedResourceMode, 3017 Type: "test_instance", 3018 Name: "new_two", 3019 }, 3020 }, 3021 }, 3022 ChangeSrc: plans.ChangeSrc{ 3023 Action: plans.Create, 3024 }, 3025 }, 3026 }, 3027 want: []map[string]interface{}{ 3028 { 3029 "@level": "error", 3030 "@message": "Terraform was interrupted during test execution, and may not have performed the expected cleanup operations.", 3031 "@module": "terraform.ui", 3032 "@testfile": "main.tftest.hcl", 3033 "test_interrupt": map[string]interface{}{ 3034 "state": []interface{}{ 3035 map[string]interface{}{ 3036 "instance": "test_instance.one", 3037 }, 3038 map[string]interface{}{ 3039 "instance": "test_instance.two", 3040 }, 3041 }, 3042 "states": map[string]interface{}{ 3043 "setup_block": []interface{}{ 3044 map[string]interface{}{ 3045 "instance": "test_instance.setup_one", 3046 }, 3047 map[string]interface{}{ 3048 "instance": "test_instance.setup_two", 3049 }, 3050 }, 3051 }, 3052 "planned": []interface{}{ 3053 "test_instance.new_one", 3054 "test_instance.new_two", 3055 }, 3056 }, 3057 "type": "test_interrupt", 3058 }, 3059 }, 3060 }, 3061 } 3062 for name, tc := range tcs { 3063 t.Run(name, func(t *testing.T) { 3064 streams, done := terminal.StreamsForTesting(t) 3065 view := NewTest(arguments.ViewJSON, NewView(streams)) 3066 3067 file := &moduletest.File{Name: "main.tftest.hcl"} 3068 run := &moduletest.Run{Name: "run_block"} 3069 3070 view.FatalInterruptSummary(run, file, tc.states, tc.changes) 3071 testJSONViewOutputEquals(t, done(t).All(), tc.want) 3072 }) 3073 } 3074 } 3075 3076 func dynamicValue(t *testing.T, value cty.Value, typ cty.Type) plans.DynamicValue { 3077 d, err := plans.NewDynamicValue(value, typ) 3078 if err != nil { 3079 t.Fatalf("failed to create dynamic value: %s", err) 3080 } 3081 return d 3082 }