Skip to main content

Testing DNS-MNS

DNS-MNS includes a comprehensive test suite that covers both the Go binary and the Bash script. This guide explains how to run the tests and what they cover.

Test Structure

tests/
├── bash/           # Bash tests using Bats
├── integration/    # Go integration tests
└── unit/           # Go unit tests (within each package)

Running Tests

Run all tests without network requirements:
make test
This runs the short test suite which completes in seconds.

Full Test Suite

Run all tests including network tests:
make test-full
Network tests require internet connectivity and may take longer to complete.

Go Tests

Unit Tests

Each internal package has comprehensive unit tests:
# Test all packages
go test -v ./...

# Test specific package
go test -v ./internal/dnslist/

# Test with coverage
go test -cover ./...

Test Coverage

Generate a coverage report:
make coverage
This creates coverage.html which you can open in your browser to see detailed coverage information.

Integration Tests

Integration tests verify the complete workflow:
make test-integration
These tests:
  • Load the embedded DNS list
  • Test ping functionality
  • Test DNS resolution
  • Verify platform detection
  • Build the binary
  • Test cross-platform compilation

Race Detection

Run tests with the race detector:
make test-race

Bash Tests

The Bash script is tested using Bats (Bash Automated Testing System).

Install Bats

brew install bats-core

Run Bash Tests

make test-bats
# or
bats tests/bash/

Test Categories

Test FileDescription
test_dnslist.batsValidates DNS list format and content
test_script.batsTests script structure and syntax
test_ping.batsTests ping functionality
test_utils.batsTests helper functions
test_integration.batsIntegration tests

What the Tests Cover

DNS List Tests

  • ✅ File exists and is readable
  • ✅ Contains all expected categories
  • ✅ All entries have valid format (NAME|IP|IP|LOCATION)
  • ✅ All IPs are valid IPv4 addresses
  • ✅ No malformed entries
  • ✅ Categories are properly defined

Go Package Tests

internal/dnslist

  • DNS list parsing from string and embedded file
  • Category filtering
  • Entry validation

internal/ping

  • Platform-specific ping output parsing
  • Average time calculation
  • Timeout handling

internal/dnstest

  • DNS resolution timing
  • Timeout handling
  • Error cases

internal/doh

  • DoH/DoT provider testing
  • Result structure validation
  • Provider list validation

internal/dnscrypt

  • DNSCrypt provider testing
  • Proxy functionality
  • Result structure validation

internal/ui

  • Color formatting
  • Progress bar rendering
  • Message formatting

internal/setter

  • Platform detection
  • Admin privilege checking
  • OS-specific code paths

Integration Tests

  • ✅ Binary can be built for all platforms
  • ✅ Embedded DNS list loads correctly
  • ✅ Complete workflow from loading to testing
  • ✅ Cross-platform compatibility

Local Testing

All testing is done locally using the Makefile and Go test commands. There is no CI/CD pipeline — run tests on your machine before committing:
make test          # Quick short tests (no network)
make test-full     # Full suite including network tests
make test-race     # Race condition detection
make coverage      # Generate coverage report

Writing New Tests

Go Tests

Follow the existing patterns in *_test.go files:
func TestNewFeature(t *testing.T) {
    tests := []struct {
        name     string
        input    string
        expected string
    }{
        {"valid case", "input", "expected"},
        {"edge case", "", ""},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            result := NewFeature(tt.input)
            if result != tt.expected {
                t.Errorf("NewFeature(%q) = %q, want %q", 
                    tt.input, result, tt.expected)
            }
        })
    }
}

Bash Tests

@test "description of what this test verifies" {
    # Run command
    run some_command
    
    # Check exit status
    [ "$status" -eq 0 ]
    
    # Check output
    [[ "$output" == *"expected content"* ]]
}

Test Best Practices

  1. Use table-driven tests for testing multiple inputs
  2. Skip network tests when running in short mode (if testing.Short())
  3. Skip admin tests when not running as root
  4. Use temporary directories for file operations
  5. Clean up after tests using t.TempDir() or teardown()

Troubleshooting

Tests fail with “permission denied”

Some tests require root/admin privileges. These are automatically skipped when not available.

Network tests timeout

Network tests may fail in restricted environments. Use make test (short mode) to skip them.

Bats tests not found

Make sure Bats is installed and in your PATH:
which bats
If not installed, see the Bats installation guide.

Makefile Commands

CommandDescription
make testRun short tests (fast)
make test-fullRun all tests
make test-batsRun Bash tests
make test-integrationRun integration tests
make test-raceRun tests with race detector
make coverageGenerate coverage report
make lintRun all linters