-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtour_test.go
More file actions
132 lines (116 loc) · 3.36 KB
/
Copy pathtour_test.go
File metadata and controls
132 lines (116 loc) · 3.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package main
import (
"fmt"
"os"
"regexp"
"strings"
"testing"
"github.com/aaccioly-coding-challenges/golang-tour-solutions/internal/capture"
)
// TestTourPositive tests successful execution scenarios using table-driven tests
func TestTourPositive(t *testing.T) {
// Save original os.Args
originalArgs := os.Args
defer func() { os.Args = originalArgs }()
// Table of positive test cases
tests := []struct {
name string
args []string
expectedOutput string
useRegex bool
regexPattern string
}{
{
name: "successful_execution_welcome_hello",
args: []string{"tour", "welcome", "hello"},
expectedOutput: "Hello, 世界\n",
useRegex: false,
},
{
name: "successful_execution_basics_packages",
args: []string{"tour", "basics", "packages"},
useRegex: true,
regexPattern: `^My favorite number is [0-9]\n$`,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
os.Args = tt.args
output := capture.CaptureOutput(main)
if tt.useRegex {
matched, err := regexp.MatchString(tt.regexPattern, output)
if err != nil {
t.Fatalf("Failed to compile regex pattern: %v", err)
}
if !matched {
t.Errorf("Expected output to match pattern %q, got %q", tt.regexPattern, output)
}
} else {
if output != tt.expectedOutput {
t.Errorf("Expected output %q, got %q", tt.expectedOutput, output)
}
}
})
}
}
// mockLogger implements the Logger interface for testing
type mockLogger struct {
fatalMsgs []string
}
func (m *mockLogger) Printf(format string, v ...interface{}) {
// No-op: we don't need to track printf calls
}
func (m *mockLogger) Println(v ...interface{}) {
// No-op: we don't need to track println calls
}
func (m *mockLogger) Fatal(v ...interface{}) {
m.fatalMsgs = append(m.fatalMsgs, fmt.Sprint(v...))
// Don't actually call os.Exit() in tests
}
func (m *mockLogger) Fatalf(format string, v ...interface{}) {
m.fatalMsgs = append(m.fatalMsgs, fmt.Sprintf(format, v...))
// Don't actually call os.Exit() in tests
}
// TestTourNegative tests error scenarios using table-driven tests with mock logger
func TestTourNegative(t *testing.T) {
// Save original os.Args
originalArgs := os.Args
defer func() { os.Args = originalArgs }()
// Table of negative test cases
tests := []struct {
name string
args []string
expectedFatalMsg string
}{
{
name: "insufficient_arguments_no_args",
args: []string{"tour"},
expectedFatalMsg: "insufficient arguments",
},
{
name: "insufficient_arguments_one_arg",
args: []string{"tour", "welcome"},
expectedFatalMsg: "insufficient arguments",
},
{
name: "nonexistent_program_failure",
args: []string{"tour", "welcome", "nonexistent"},
expectedFatalMsg: "Failed to run welcome/nonexistent",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mock := &mockLogger{}
os.Args = tt.args
runMain(mock)
// Check fatal messages
if tt.expectedFatalMsg != "" {
if len(mock.fatalMsgs) == 0 {
t.Error("Expected fatal call, got none")
} else if !strings.Contains(mock.fatalMsgs[0], tt.expectedFatalMsg) {
t.Errorf("Expected fatal message to contain %q, got %q", tt.expectedFatalMsg, mock.fatalMsgs[0])
}
}
})
}
}