Search⌘ K
AI Features

Solution 2: Code Testing and Profiling

Explore how to write effective test functions in Go to validate code correctness and use profiling techniques to optimize performance. This lesson helps you understand testing key functions and capturing output to ensure your Go applications run reliably.

We'll cover the following...
...
package main

import (
	"os"
	"testing"
	"strings"
)

func TestReadCSVFile(t *testing.T) {
	// Create a temporary test CSV file
	tmpFile := "/tmp/test.csv"
	f, err := os.Create(tmpFile)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()

	// Write test data to the temporary file
	testData := "John,Doe,1234567890,123456789\nJane,Smith,9876543210,987654321\n"
	_, err = f.WriteString(testData)
	if err != nil {
		t.Fatal(err)
	}

	// Call readCSVFile to read the temporary file
	err = readCSVFile(tmpFile)
	if err != nil {
		t.Fatal(err)
	}

	// Check if data is loaded correctly
	if len(data) != 2 {
		t.Fatalf("Expected 2 entries, got %d", len(data))
	}

	// Clean up the temporary file
	err = os.Remove(tmpFile)
	if err != nil {
		t.Fatal(err)
	}
}

// A setup function to clear data before tests
func setup() {
    data = []Entry{}
    index = make(map[string]int)
}

func TestInsert(t *testing.T) {
    // Set up the test environment
    setup()
	// Initialize test data
	testEntry := initS("Test", "User", "5551234567")
	if testEntry == nil {
		t.Fatal("Failed to initialize test entry")
	}

	// Call insert to insert the test entry
	err := insert(testEntry)
	if err != nil {
		t.Fatal(err)
	}

	// Check if the test entry was inserted
	if len(data) != 1 {
		t.Fatalf("Expected 1 entry after insert, got %d", len(data))
	}

	// Clean up by deleting the test entry
	err = deleteEntry("5551234567")
	if err != nil {
		t.Fatal(err)
	}
}

func TestDeleteEntry(t *testing.T) {
	// Initialize test data
	testEntry := initS("Test", "User", "5551234567")
	if testEntry == nil {
		t.Fatal("Failed to initialize test entry")
	}

	// Insert the test entry
	err := insert(testEntry)
	if err != nil {
		t.Fatal(err)
	}

	// Call deleteEntry to delete the test entry
	err = deleteEntry("5551234567")
	if err != nil {
		t.Fatal(err)
	}

	// Check if the test entry was deleted
	if len(data) != 0 {
		t.Fatalf("Expected 0 entries after delete, got %d", len(data))
	}
}

func TestSearch(t *testing.T) {
	// Initialize test data
	testEntry := initS("Test", "User", "5551234567")
	if testEntry == nil {
		t.Fatal("Failed to initialize test entry")
	}

	// Insert the test entry
	err := insert(testEntry)
	if err != nil {
		t.Fatal(err)
	}

	// Call search to find the test entry
	result := search("5551234567")
	if result == nil {
		t.Fatal("Failed to find test entry")
	}

	// Clean up by deleting the test entry
	err = deleteEntry("5551234567")
	if err != nil {
		t.Fatal(err)
	}
}

func TestList(t *testing.T) {
	// Set up test data
	setup()
	testData := []Entry{
		{Name: "John", Surname: "Doe", Tel: "1234567890", LastAccess: "123456789"},
		{Name: "Jane", Surname: "Smith", Tel: "9876543210", LastAccess: "987654321"},
	}
	data = append(data, testData...)

	// Redirect standard output to capture printed output
	oldStdout := os.Stdout
	r, w, _ := os.Pipe()
	os.Stdout = w

	// Call the list function
	list()

	// Close the pipe and restore stdout
	w.Close()
	os.Stdout = oldStdout

	// Read the captured output from the pipe
	outputBytes := make([]byte, 4096)
	n, _ := r.Read(outputBytes)

	// Convert the captured output to a string and split it into lines
	output := string(outputBytes[:n])
	lines := strings.Split(output, "\n")

	// Check if the number of lines matches the number of entries in the test data
	if len(lines)-1 != len(testData) { // Subtract 1 to account for the final newline
		t.Fatalf("Expected %d lines in output, got %d", len(testData), len(lines)-1)
	}
}

func TestMatchTel(t *testing.T) {
	// Test cases for matchTel
	testCases := []struct {
		input    string
		expected bool
	}{
		{"1234567890", true},   // Valid telephone number
		{"9876543210", true},   // Valid telephone number
		{"abcd", false},         // Non-digit characters
		{"", false},             // Empty string
	}

	// Run test cases
	for _, tc := range testCases {
		result := matchTel(tc.input)
		if result != tc.expected {
			t.Errorf("For input %s, expected %v, but got %v", tc.input, tc.expected, result)
		}
	}
}
phoneBook.go and phoneBook_test.go
...