Add Tests
The testing
module provides a framework for writing and running tests. It encourages writing simple and expressive tests to ensure the correctness of your code.
In Go, test files are identified by their file names. The convention for naming test files is to use the _test.go
suffix. This naming convention signals to the Go tooling that the file contains test code.
Test functions are functions whose names start with Test
. They take a single argument of type *testing.T
. You can use t.Error
or t.Fail
to indicate a test failure.
pkg/grep/search_test.go:
package grep
import (
"os"
"path/filepath"
"reflect"
"testing"
)
func TestGrep(t *testing.T) {
// Create a temporary file for testing
tmpfile, err := os.CreateTemp("", "example")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpfile.Name())
// Write some content to the temporary file
content := "line1\nline2\nline3\npattern\nline4"
if _, err := tmpfile.Write([]byte(content)); err != nil {
t.Fatal(err)
}
// Close the file before testing
if err := tmpfile.Close(); err != nil {
t.Fatal(err)
}
// Test Grep function
pattern := "pattern"
options := &Options{}
result, err := Grep(pattern, tmpfile.Name(), options)
if err != nil {
t.Fatal(err)
}
expectedResult := MatchResult{
tmpfile.Name(): {
{LineNumber: 4, Line: "pattern"},
},
}
if !reflect.DeepEqual(result, expectedResult) {
t.Errorf("Expected %v, but got %v", expectedResult, result)
}
}
func TestGrepCount(t *testing.T) {
// Test cases for GrepCount function
t.Run("EmptyResult", func(t *testing.T) {
result := make(MatchResult)
count := GrepCount(result)
expectedCount := 0
if count != expectedCount {
t.Errorf("Expected count %v, but got %v", expectedCount, count)
}
})
t.Run("NonEmptyResult", func(t *testing.T) {
result := MatchResult{
"file1.txt": {
{LineNumber: 1, Line: "pattern"},
{LineNumber: 5, Line: "pattern"},
},
"file2.txt": {
{LineNumber: 3, Line: "pattern"},
},
}
count := GrepCount(result)
expectedCount := 3
if count != expectedCount {
t.Errorf("Expected count %v, but got %v", expectedCount, count)
}
})
}
func TestGrepRecursive(t *testing.T) {
// Create a temporary directory for testing
tmpdir, err := os.MkdirTemp("", "example")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpdir)
// Create nested files and directories
files := []string{
"file1.txt",
"file2.txt",
"subdir/file3.txt",
"subdir/file4.txt",
}
for _, file := range files {
filePath := filepath.Join(tmpdir, file)
if err := os.MkdirAll(filepath.Dir(filePath), os.ModePerm); err != nil {
t.Fatal(err)
}
// Write some content to the files
content := "pattern"
if err := os.WriteFile(filePath, []byte(content), os.ModePerm); err != nil {
t.Fatal(err)
}
}
// Test GrepRecursive function
pattern := "pattern"
options := &Options{}
result, err := GrepRecursive(pattern, tmpdir, options)
if err != nil {
t.Fatal(err)
}
expectedResult := MatchResult{
filepath.Join(tmpdir, "file1.txt"): {
{LineNumber: 1, Line: "pattern"},
},
filepath.Join(tmpdir, "file2.txt"): {
{LineNumber: 1, Line: "pattern"},
},
filepath.Join(tmpdir, "subdir/file3.txt"): {
{LineNumber: 1, Line: "pattern"},
},
filepath.Join(tmpdir, "subdir/file4.txt"): {
{LineNumber: 1, Line: "pattern"},
},
}
if !reflect.DeepEqual(result, expectedResult) {
t.Errorf("Expected %v, but got %v", expectedResult, result)
}
}
Tests are run using the go test
command:
go test ./...
# Or -v for verbose output
go test -v ./...
You should get test results as below:
=== RUN TestGrep
--- PASS: TestGrep (0.00s)
=== RUN TestGrepCount
=== RUN TestGrepCount/EmptyResult
=== RUN TestGrepCount/NonEmptyResult
--- PASS: TestGrepCount (0.00s)
--- PASS: TestGrepCount/EmptyResult (0.00s)
--- PASS: TestGrepCount/NonEmptyResult (0.00s)
=== RUN TestGrepRecursive
--- PASS: TestGrepRecursive (0.00s)
PASS
ok github.com/Literank/gorep/pkg/grep
If there's something wrong, you will get a detailed error messge like this:
=== RUN TestGrep
search_test.go:43: Expected map[/var/folders/wx/hdjympxj7h3_ntwgzbhddyr40000gn/T/example236042624:[0xc0000b40c0]], but got map[/var/folders/wx/hdjympxj7h3_ntwgzbhddyr40000gn/T/example236042624:[0xc0000b40a8]]
--- FAIL: TestGrep (0.00s)
=== RUN TestGrepCount
=== RUN TestGrepCount/EmptyResult
=== RUN TestGrepCount/NonEmptyResult
--- PASS: TestGrepCount (0.00s)
--- PASS: TestGrepCount/EmptyResult (0.00s)
--- PASS: TestGrepCount/NonEmptyResult (0.00s)
=== RUN TestGrepRecursive
--- PASS: TestGrepRecursive (0.00s)
FAIL
FAIL github.com/Literank/gorep/pkg/grep 1.649s
FAIL
Then, you can fix your code based on this error message.