mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-02-18 19:51:08 +00:00
feat(lint): add many linters, make all the tests run fast! (#23)
* chore(lint): added nlreturn, run linting * chore(lint): replace some fmt.Sprintf calls * chore(lint): replace fmt.Sprintf with strconv * chore(lint): add goconst, use http lib for status codes, and methods * chore(lint): use errors lib, errCodes from internal/errors * chore(lint): dupl, thelper and usetesting * chore(lint): fmt.Errorf %v to %w, more linters * chore(lint): paralleltest, where possible * perf(test): optimize test performance by 78% - Implement shared binary building with package-level cache to eliminate redundant builds - Add strategic parallelization to 15+ tests while preserving environment variable isolation - Implement thread-safe fixture caching with RWMutex to reduce I/O operations - Remove unnecessary working directory changes by leveraging embedded templates - Add embedded template system with go:embed directive for reliable template resolution - Fix linting issues: rename sharedBinaryError to errSharedBinary, add nolint directive Performance improvements: - Total test execution time: 12+ seconds → 2.7 seconds (78% faster) - Binary build overhead: 14+ separate builds → 1 shared build (93% reduction) - Parallel execution: Limited → 15+ concurrent tests (60-70% better CPU usage) - I/O operations: 66+ fixture reads → cached with sync.RWMutex (50% reduction) All tests maintain 100% success rate and coverage while running nearly 4x faster.
This commit is contained in:
@@ -12,8 +12,10 @@ func CreateAnalyzer(generator *internal.Generator, output *internal.ColoredOutpu
|
||||
analyzer, err := generator.CreateDependencyAnalyzer()
|
||||
if err != nil {
|
||||
output.Warning("Could not create dependency analyzer: %v", err)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return analyzer
|
||||
}
|
||||
|
||||
@@ -24,5 +26,6 @@ func CreateAnalyzerOrExit(generator *internal.Generator, output *internal.Colore
|
||||
// Error already logged, just exit
|
||||
return nil
|
||||
}
|
||||
|
||||
return analyzer
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
)
|
||||
|
||||
func TestCreateAnalyzer(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setupConfig func() *internal.AppConfig
|
||||
@@ -48,6 +50,8 @@ func TestCreateAnalyzer(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
config := tt.setupConfig()
|
||||
generator := internal.NewGenerator(config)
|
||||
|
||||
@@ -74,6 +78,8 @@ func TestCreateAnalyzer(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateAnalyzerOrExit(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Only test success case since failure case calls os.Exit
|
||||
t.Run("successful analyzer creation", func(t *testing.T) {
|
||||
config := &internal.AppConfig{
|
||||
@@ -103,6 +109,8 @@ func TestCreateAnalyzerOrExit(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateAnalyzer_Integration(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// Test integration with actual generator functionality
|
||||
tmpDir, cleanup := testutil.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -15,6 +15,7 @@ func GetCurrentDir() (string, error) {
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error getting current directory: %w", err)
|
||||
}
|
||||
|
||||
return currentDir, nil
|
||||
}
|
||||
|
||||
@@ -31,12 +32,14 @@ func SetupGeneratorContext(config *internal.AppConfig) (*internal.Generator, str
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return generator, currentDir, nil
|
||||
}
|
||||
|
||||
// FindGitRepoRoot finds git repository root with standardized error handling.
|
||||
func FindGitRepoRoot(currentDir string) string {
|
||||
repoRoot, _ := git.FindRepositoryRoot(currentDir)
|
||||
|
||||
return repoRoot
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
)
|
||||
|
||||
func TestGetCurrentDir(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("successfully get current directory", func(t *testing.T) {
|
||||
currentDir, err := GetCurrentDir()
|
||||
|
||||
@@ -33,6 +35,8 @@ func TestGetCurrentDir(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetupGeneratorContext(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
config *internal.AppConfig
|
||||
@@ -71,6 +75,8 @@ func TestSetupGeneratorContext(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
generator, currentDir, err := SetupGeneratorContext(tt.config)
|
||||
|
||||
// Verify no error occurred
|
||||
@@ -79,6 +85,7 @@ func TestSetupGeneratorContext(t *testing.T) {
|
||||
// Verify generator was created
|
||||
if generator == nil {
|
||||
t.Error("expected generator to be created")
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@@ -100,6 +107,8 @@ func TestSetupGeneratorContext(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindGitRepoRoot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
setupFunc func(t *testing.T, tmpDir string) string
|
||||
@@ -108,6 +117,7 @@ func TestFindGitRepoRoot(t *testing.T) {
|
||||
{
|
||||
name: "directory with git repository",
|
||||
setupFunc: func(t *testing.T, tmpDir string) string {
|
||||
t.Helper()
|
||||
// Create .git directory
|
||||
gitDir := filepath.Join(tmpDir, ".git")
|
||||
err := os.MkdirAll(gitDir, 0750) // #nosec G301 -- test directory permissions
|
||||
@@ -133,6 +143,7 @@ func TestFindGitRepoRoot(t *testing.T) {
|
||||
{
|
||||
name: "nested directory in git repository",
|
||||
setupFunc: func(t *testing.T, tmpDir string) string {
|
||||
t.Helper()
|
||||
// Create .git directory at root
|
||||
gitDir := filepath.Join(tmpDir, ".git")
|
||||
err := os.MkdirAll(gitDir, 0750) // #nosec G301 -- test directory permissions
|
||||
@@ -151,6 +162,8 @@ func TestFindGitRepoRoot(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmpDir, cleanup := testutil.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -172,7 +185,11 @@ func TestFindGitRepoRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetGitRepoRootAndInfo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("valid git repository with complete info", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmpDir, cleanup := testutil.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -187,6 +204,8 @@ func TestGetGitRepoRootAndInfo(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("git repository but info detection fails", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmpDir, cleanup := testutil.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -201,6 +220,8 @@ func TestGetGitRepoRootAndInfo(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("directory without git repository", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
tmpDir, cleanup := testutil.TempDir(t)
|
||||
defer cleanup()
|
||||
|
||||
@@ -220,6 +241,7 @@ func TestGetGitRepoRootAndInfo(t *testing.T) {
|
||||
|
||||
// Helper functions to reduce complexity.
|
||||
func setupCompleteGitRepo(t *testing.T, tmpDir string) string {
|
||||
t.Helper()
|
||||
// Create .git directory
|
||||
gitDir := filepath.Join(tmpDir, ".git")
|
||||
err := os.MkdirAll(gitDir, 0750) // #nosec G301 -- test directory permissions
|
||||
@@ -245,6 +267,7 @@ func setupCompleteGitRepo(t *testing.T, tmpDir string) string {
|
||||
}
|
||||
|
||||
func setupMinimalGitRepo(t *testing.T, tmpDir string) string {
|
||||
t.Helper()
|
||||
// Create .git directory but with minimal content
|
||||
gitDir := filepath.Join(tmpDir, ".git")
|
||||
err := os.MkdirAll(gitDir, 0750) // #nosec G301 -- test directory permissions
|
||||
@@ -254,6 +277,7 @@ func setupMinimalGitRepo(t *testing.T, tmpDir string) string {
|
||||
}
|
||||
|
||||
func verifyRepoRoot(t *testing.T, repoRoot, tmpDir string) {
|
||||
t.Helper()
|
||||
if repoRoot != "" && !strings.Contains(repoRoot, tmpDir) {
|
||||
t.Errorf("expected repo root to be within %s, got %s", tmpDir, repoRoot)
|
||||
}
|
||||
@@ -261,7 +285,11 @@ func verifyRepoRoot(t *testing.T, repoRoot, tmpDir string) {
|
||||
|
||||
// Test error handling in GetGitRepoRootAndInfo.
|
||||
func TestGetGitRepoRootAndInfo_ErrorHandling(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
t.Run("nonexistent directory", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
nonexistentPath := "/this/path/should/not/exist"
|
||||
repoRoot, gitInfo, err := GetGitRepoRootAndInfo(nonexistentPath)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user