Skip to content

VM Tracker Client - Unit Tests

Overview

This project contains comprehensive unit tests for the VM Tracker Client, written in Go.

Test Coverage

Current Coverage: 27.7% of statements (focused on testable business logic)

Detailed Coverage by Function:

Function Coverage Description
getHostname 60.0% Tests for hostname detection
getIPAddress 81.8% Tests for IP address detection
Post (DefaultHTTPClient) 100.0% HTTP client wrapper
sendRegistrationWithClient 83.3% Registration logic with mock HTTP client

Note: The main() function (0% coverage) is not tested as it contains orchestration logic that is better covered by integration tests.

Test Categories

1. JSON Marshaling/Unmarshaling Tests

  • TestVMInfoJSONMarshaling: Tests correct serialization and deserialization of VMInfo
  • Covers normal cases, empty fields, and special characters
  • Ensures JSON tags work correctly

2. Hostname Tests

  • TestGetHostname: Validates hostname detection
  • Verifies that a valid hostname is returned

3. IP Address Tests

  • TestGetIPAddress: Comprehensive tests for network interface detection
  • Valid interface names
  • Invalid interface names
  • Empty interface names
  • Validates IPv4 format
  • Automatically detects available network interfaces

4. HTTP Registration Tests

  • TestSendRegistrationSuccess: Successful registration
  • TestSendRegistrationHTTPErrors: HTTP error scenarios
  • 400 Bad Request
  • 401 Unauthorized
  • 404 Not Found
  • 500 Internal Server Error
  • 503 Service Unavailable
  • Network connection errors
  • TestSendRegistrationURLFormatting: URL formatting
  • URLs with/without trailing slash
  • URLs with port
  • HTTPS URLs
  • Localhost

5. Edge Cases & Validation

  • TestVMInfoFieldValidation: Field validation
  • Very long hostnames (255 characters)
  • IPv6-mapped IPv4 addresses
  • Complex interface names
  • TestDefaultHTTPClient: HTTP client wrapper

Benchmarks

Performance tests for critical operations:

BenchmarkVMInfoMarshaling-8         11367013           110.8 ns/op        80 B/op          1 allocs/op
BenchmarkVMInfoUnmarshaling-8        1992078           606.0 ns/op       296 B/op          8 allocs/op

Interpretation: - Marshaling: ~111 ns per operation, very efficient - Unmarshaling: ~606 ns per operation, acceptable for JSON parsing - Low memory allocations

Running Tests

Run all tests:

go test -v

Tests with coverage:

go test -v -cover

Detailed coverage report:

go test -coverprofile=coverage.out
go tool cover -func=coverage.out

HTML coverage visualization:

go test -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
# Open coverage.html in a browser

Run benchmarks:

go test -bench=. -benchmem

Run specific tests:

# Only JSON tests
go test -v -run TestVMInfoJSON

# Only IP address tests
go test -v -run TestGetIPAddress

# Only HTTP tests
go test -v -run TestSendRegistration

Mock Architecture

The tests use a mock-based architecture for HTTP calls:

HTTPClient Interface

type HTTPClient interface {
    Post(url, contentType string, body *bytes.Buffer) (*http.Response, error)
}

Benefits:

  • ✅ No real network calls in tests
  • ✅ Full control over HTTP responses
  • ✅ Tests are fast and deterministic
  • ✅ Easy testing of error scenarios
  • ✅ No external dependencies

Code Changes for Testability

The main.go was minimally refactored:

  1. HTTPClient Interface: Enables mocking of HTTP calls
  2. DefaultHTTPClient: Production implementation
  3. sendRegistrationWithClient: Testable version with dependency injection
  4. sendRegistration: Wrapper for production code (unchanged API)

These changes: - ✅ Don't break existing functionality - ✅ Are backwards compatible - ✅ Enable comprehensive tests without real network calls

Best Practices

The tests follow Go best practices:

  1. Table-Driven Tests: Multiple test cases in one test function
  2. Subtests: Structured organization with t.Run()
  3. Clear Naming: Descriptive test and subtest names
  4. Mocking: Interface-based mocking for external dependencies
  5. Error Checking: Comprehensive error handling
  6. Benchmarking: Performance measurements for critical paths

Continuous Integration

These tests can easily be integrated into CI/CD pipelines:

# Example GitHub Actions
- name: Run tests
  run: go test -v -coverprofile=coverage.out

- name: Upload coverage
  run: go tool cover -html=coverage.out -o coverage.html

Future Enhancements

Possible test extensions:

  • [ ] Integration tests for the entire main() function
  • [ ] Tests for signal handling (SIGTERM, SIGINT)
  • [ ] Tests for retry logic
  • [ ] Tests for ticker-based updates
  • [ ] Mock server for end-to-end tests
  • [ ] Property-based tests with fuzzing

Troubleshooting

Tests fail with "no valid network interface"

  • This is normal when no non-loopback IPv4 interfaces are available
  • The test is automatically skipped (t.Skip())

Coverage seems low

  • The 27.7% coverage focuses on business logic
  • main() and orchestration are intentionally not tested
  • These are better covered by integration tests

Contact

For questions or problems with the tests, please create an issue.