A Go static analysis tool that identifies missing test coverage and misplaced test functions in your Go projects.
- Missing Test Detection: Finds functions and methods not called from any test function
- Low Coverage Detection: Identifies functions with statement coverage below a threshold (uses
go test -cover) - AST-Based Call Analysis: Analyzes actual function calls in tests, not naming conventions
- Misplaced Test Detection: Identifies tests that primarily call functions from a different source file
- Method Support: Handles methods with receivers, including generics
- Flexible Filtering: Option to exclude private (unexported) functions from analysis
- Clean Output: Organized results grouped by file with line numbers
go install github.com/LeanerCloud/testvet@latestOr build from source:
git clone https://github.com/LeanerCloud/testvet.git
cd testvet
go build -o testvet .# Analyze current directory (runs go test for coverage data by default)
testvet
# Analyze a specific directory
testvet -dir /path/to/your/project
# Exclude private (unexported) functions
testvet -dir . -exclude-private
# Show verbose output (parse warnings)
testvet -dir . -verbose
# Show functions with statement coverage below 80%
testvet -threshold 80
# Disable coverage filtering (AST-only analysis, faster but less accurate)
testvet -use-coverage=false================================================================================
GO TEST COVERAGE ANALYSIS
================================================================================
Project: /path/to/your/project
--------------------------------------------------------------------------------
FUNCTIONS WITHOUT TEST COVERAGE (3)
--------------------------------------------------------------------------------
handlers/user.go:
Line 25: CreateUser
Line 48: (UserService).ValidateEmail
utils/helpers.go:
Line 12: parseConfig
--------------------------------------------------------------------------------
MISPLACED TESTS (1)
--------------------------------------------------------------------------------
TestCreateUser (line 15):
Current file: handlers/api_test.go
Expected file: handlers/user_test.go
================================================================================
Summary: 3 functions without tests, 1 misplaced tests
When using -threshold, testvet also runs go test -cover and reports functions with statement coverage below the specified percentage:
--------------------------------------------------------------------------------
LOW COVERAGE FUNCTIONS (below 80.0%) (2)
--------------------------------------------------------------------------------
handlers/user.go:
Line 25: CreateUser (45.5%)
Line 48: ValidateEmail (72.0%)
================================================================================
Summary: 0 functions without tests, 0 misplaced tests, 2 low coverage functions
This helps identify functions that have tests but need more thorough testing (e.g., missing error path coverage).
- Parsing: Uses Go's
go/astpackage to parse all.gofiles in the target directory - Function Extraction: Extracts all function and method declarations from source files
- Test Extraction: Identifies test functions (
Test*,Benchmark*,Example*,Fuzz*) from_test.gofiles - Call Analysis: Walks the AST of each test function to find all function calls within it
- Coverage Filtering (default): Runs
go test -coverprofileand excludes functions with >=50% coverage from the "missing tests" list (catches indirectly tested functions) - Matching: A function is considered tested if it's called from any test function or has adequate coverage
- Misplacement Detection: A test is misplaced if it primarily calls functions from a different source file
main()andinit()functionsvendor/directorytestdata/directory- Hidden directories (starting with
.)
| Flag | Default | Description |
|---|---|---|
-dir |
. |
Directory to analyze |
-exclude-private |
false |
Exclude unexported functions from analysis |
-verbose |
false |
Show verbose output including parse warnings |
-threshold |
0 |
Show functions with statement coverage below this percentage (0 to disable, excludes main/init) |
-use-coverage |
true |
Use coverage data to filter out indirectly tested functions (functions with >=50% coverage are considered tested) |
These tools measure different aspects of test coverage:
| Aspect | testvet | go test -cover |
|---|---|---|
| Question answered | Is this function called from any test? | What percentage of statements are executed? |
| Granularity | Per function (binary: yes/no) | Per statement (percentage) |
| Use case | Find completely untested functions | Measure thoroughness of existing tests |
Example: A function with complex error handling might show:
- testvet: ✓ covered (called from a test)
- go test -cover: 60% (only the happy path is tested)
Both metrics are valuable:
- Use testvet to find functions with zero test coverage
- Use testvet -threshold N to find functions with low statement coverage
- Use go test -cover to measure overall statement coverage
# Find untested functions
testvet .
# Find functions with <80% statement coverage
testvet -threshold 80
# Measure overall statement coverage
go test -cover ./...
# View detailed coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.outThe -threshold flag bridges both approaches: it uses go test -cover under the hood but presents results in testvet's familiar format, making it easy to identify poorly-tested functions that need attention.
- AST analysis only detects direct function calls within test functions (not calls from helper functions)
Contributions are welcome! Please feel free to submit a Pull Request.
MIT License - see LICENSE for details.
This tool is brought to you by LeanerCloud. We help companies reduce their cloud costs using a mix of services and tools such as AutoSpotting.
Running at significant scale on AWS and looking for cost optimization help? Contact us.