Testing package overview in Go - Time & Space Complexity
When using Go's testing package, it's important to know how the time your tests take grows as you add more tests or more data.
We want to understand how the testing process scales with the size of the input or number of tests.
Analyze the time complexity of the following test function using Go's testing package.
func TestSum(t *testing.T) {
for i := 0; i < len(testCases); i++ {
got := Sum(testCases[i].input)
if got != testCases[i].expected {
t.Errorf("Sum(%v) = %v; want %v", testCases[i].input, got, testCases[i].expected)
}
}
}
This code runs a test for each input in a list, checking if the Sum function returns the expected result.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Looping through all test cases to run each test.
- How many times: Once for each test case in the testCases slice.
As the number of test cases increases, the total time to run tests grows proportionally.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | Runs 10 tests |
| 100 | Runs 100 tests |
| 1000 | Runs 1000 tests |
Pattern observation: The time grows linearly as you add more test cases.
Time Complexity: O(n)
This means the time to run tests increases directly with the number of test cases.
[X] Wrong: "Adding more test cases won't affect test run time much."
[OK] Correct: Each test case runs separately, so more tests mean more time spent running them all.
Understanding how test time grows helps you write efficient tests and manage testing time well in real projects.
"What if each test case called another function that itself loops over data? How would the time complexity change?"
Practice
testing package in Go?Solution
Step 1: Understand the role of the testing package
The testing package is designed to help write tests that verify code correctness.Step 2: Identify the correct purpose
It does not handle GUIs, databases, or compilation speed but focuses on testing functions.Final Answer:
To write functions that check if your code works correctly -> Option DQuick Check:
testing package = write test functions [OK]
- Confusing testing with UI or database packages
- Thinking it speeds up compilation
- Assuming it manages runtime behavior
Solution
Step 1: Recall test function naming rules
Test functions must start with uppercase 'Test' followed by the function name.Step 2: Match the correct naming pattern
Only func TestMyFunction(t *testing.T) {} uses 'Test' prefix correctly and has the right signature.Final Answer:
func TestMyFunction(t *testing.T) {} -> Option AQuick Check:
Test functions start with 'Test' [OK]
- Starting function name with lowercase 'test'
- Placing 'Test' at the end of the function name
- Using incorrect function signature
go test on this test file?package main
import "testing"
func TestSum(t *testing.T) {
total := 2 + 3
if total != 5 {
t.Error("Sum was incorrect")
}
}Solution
Step 1: Analyze the test logic
The test calculates 2 + 3 and checks if it equals 5, which is true, so no error is called.Step 2: Understand test output
Since the test passes,go testreports PASS with timing info.Final Answer:
PASS ok main 0.001s -> Option CQuick Check:
Correct test = PASS output [OK]
- Assuming test fails without error call
- Confusing syntax errors with test failures
- Expecting output when no tests exist
package main
import "testing"
func TestMultiply(t *testing.T) {
result := 3 * 4
if result = 12 {
t.Log("Multiplication correct")
}
}Solution
Step 1: Check the if condition syntax
The condition uses '=' which assigns value instead of '==' which compares values.Step 2: Understand Go syntax rules
Using '=' in if condition causes a compile error; '==' is needed for comparison.Final Answer:
Using assignment '=' instead of comparison '==' in if condition -> Option BQuick Check:
Use '==' for comparison in if [OK]
- Confusing assignment '=' with equality '=='
- Thinking t.Log is disallowed
- Ignoring function naming conventions
func TestNonEmpty(t *testing.T) {
result := getName()
// Which check is correct?
}Solution
Step 1: Understand the test goal
The test must fail if the returned string is empty, so check if result equals empty string.Step 2: Choose the correct condition
if result == "" { t.Error("Result should not be empty") } checks if result == "" and calls t.Error, which correctly fails the test on empty string.Final Answer:
if result == "" { t.Error("Result should not be empty") } -> Option AQuick Check:
Fail test when string is empty [OK]
- Using != instead of == for empty check
- Comparing string to nil or 0
- Not calling t.Error on failure condition
Ready to prove it?
Pass the test and this pattern moves unknown
