Skip to content

A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.

Notifications You must be signed in to change notification settings

bukinator-dev/legacy-analyzer

Repository files navigation

Java Legacy Analyzer

A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.

🎯 Features

  • πŸ“Š Code Analysis: Deep analysis of Java classes including complexity, dependencies, and testability
  • πŸ§ͺ Mock Generation: Automatically generates Mockito test classes with proper annotations
  • πŸ”— API Sequence Mapping: Traces method call sequences up to 4 levels deep across files
  • 🌲 Visual Tree Display: Shows method invocation hierarchy in ASCII tree format
  • πŸ“ Organized Output: Auto-creates separate directories for generated tests and API reports
  • πŸ” Risk Detection: Identifies high-risk areas that need thorough testing
  • πŸ’‘ Smart Suggestions: Provides specific test coverage recommendations
  • 🎨 Cross-Platform: Works on Windows, Linux, and macOS with ASCII-safe output

πŸ“‹ Table of Contents

  1. Installation
  2. Quick Start
  3. Commands Reference
  4. Understanding API Analysis
  5. Interpreting Results
  6. Output Directory Structure
  7. Use Cases & Examples
  8. Best Practices

πŸš€ Installation

Requirements:

  • Python 3.7 or higher
  • No external dependencies required (pure Python!)

Setup:

# Clone or download the repository
cd legacy-analyzer

# Make the CLI executable (Unix/Linux/macOS)
chmod +x legacy-cli

# Ready to use!
./legacy-cli --help

# On Windows, use:
legacy-cli.bat --help

# Or use Python directly on any platform:
python main.py --help

Adding to PATH (Optional):

# Unix/Linux/macOS - Add to ~/.bashrc or ~/.zshrc
export PATH="$PATH:/path/to/legacy-analyzer"

# Windows - Add the directory to your System PATH environment variable
# Then you can use: legacy-cli analyze MyFile.java

⚑ Quick Start

1. Analyze a Single Java Class

# Using legacy-cli (recommended)
./legacy-cli analyze examples/UserService.java

# Or with Python directly
python main.py analyze examples/UserService.java

What you'll see:

  • Complexity breakdown (Simple/Moderate/Complex methods)
  • Mockable dependencies
  • Testability score (0-100)
  • Test coverage suggestions
  • Risk areas

2. Generate Test Class with Mocks

# Using legacy-cli (recommended)
./legacy-cli generate examples/UserService.java --output UserServiceTest.java

# Or with Python directly
python main.py generate examples/UserService.java --output UserServiceTest.java

Output: generated-tests/UserServiceTest.java (auto-created directory)

Contains:

  • @Mock annotations for dependencies
  • @InjectMocks for class under test
  • Test method stubs for all public methods
  • Exception test cases

3. Analyze Project APIs (Entire Codebase)

# Using legacy-cli (recommended)
./legacy-cli api-analyze examples

# Or with Python directly
python main.py api-analyze examples

What you'll see:

  • All public APIs (methods) discovered
  • Tree view of method invocation sequences
  • Cross-file method call tracking
  • External API dependencies highlighted
  • Exception handling paths

πŸ“– Commands Reference

analyze - Single File Analysis

Analyzes a Java class for testability and complexity.

# Using legacy-cli
./legacy-cli analyze <java-file> [--verbose]

# Or with Python
python main.py analyze <java-file> [--verbose]

Options:

  • --verbose, -v - Show detailed analysis

Example:

./legacy-cli analyze examples/UserService.java --verbose

Output Sections:

  1. Complexity Analysis: Method count breakdown
  2. Dependencies: Mockable fields
  3. Testability Score: 0-100 rating
  4. Test Coverage Suggestions: What to test
  5. Risk Areas: High-priority test targets
  6. Public Methods: List of testable methods

generate - Generate Test Class

Creates a complete JUnit + Mockito test class.

# Using legacy-cli
./legacy-cli generate <java-file> [options]

# Or with Python
python main.py generate <java-file> [options]

Options:

  • --output, -o FILE - Output file name (saved to generated-tests/)
  • --quick-mocks - Generate only mock field declarations
  • --no-setup - Skip @Before setup method

Examples:

# Full test class
./legacy-cli generate examples/UserService.java --output UserServiceTest.java
# Output: generated-tests/UserServiceTest.java

# Quick mocks only (for copy-paste)
./legacy-cli generate examples/UserService.java --quick-mocks

# Save to custom location (absolute path)
./legacy-cli generate examples/UserService.java --output /tmp/MyTest.java

Generated Test Structure:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceTest {
    @Mock
    private UserDAO userDAO;

    @InjectMocks
    private UserService userService;

    @Before
    public void setUp() { }

    @Test
    public void testGetUserById_Success() { }

    @Test(expected = Exception.class)
    public void testGetUserById_ThrowsException() { }
}

api-analyze - Project-Wide API Analysis

Scans entire project to map all public APIs and their invocation sequences.

# Using legacy-cli
./legacy-cli api-analyze <project-directory> [options]

# Or with Python
python main.py api-analyze <project-directory> [options]

Options:

  • --export, -e FILE - Export to markdown (saved to api-reports/)
  • --summary - Show only summary table

Examples:

# Full analysis with tree view
./legacy-cli api-analyze examples

# Export to markdown report
./legacy-cli api-analyze examples --export api-report.md
# Output: api-reports/api-report.md

# Show summary table only
./legacy-cli api-analyze examples --summary

πŸ” Understanding API Analysis

What is Analyzed?

The api-analyze command discovers:

  1. Public APIs: All public methods (excluding constructors)
  2. Call Sequences: Method invocation chains up to 4 levels deep
  3. Cross-File Calls: Methods calling other methods in different files
  4. External Dependencies: Calls to libraries, frameworks, databases
  5. Exception Paths: Thrown and caught exceptions

How Sequences are Traced

API Method (depth 0)
β”œβ”€β”€ Internal Method Call (depth 1)
β”‚   β”œβ”€β”€ External DB Call (depth 2)
β”‚   └── External Logger Call (depth 2)
└── External API Call (depth 1)

Depth Limits:

  • Maximum depth: 4 levels
  • Prevents infinite recursion
  • Stops at external dependencies

πŸ“Š Interpreting Results

Tree View Symbols

|--  Non-last item in list (has siblings below)
+--  Last item in list (no more siblings)
|    Continuation line (parent has more children)
     Spacing (parent is complete)

Example Output:

Call Sequence (Tree View):
  |-- newEmail.contains("@")
  |-- user.setEmail(newEmail)
  |-- UserDAO.update(user)
  +-- [UserService.java] UserService.getUserById(userId)
      |-- [EXTERNAL] Logger.info("Getting user...") (depth: 1)
      |-- [EXTERNAL] UserDAO.findById(userId) (depth: 1)
      +-- [EXTERNAL] Logger.warn("User not found") (depth: 1)

Interpretation:

  1. updateUserEmail calls 4 methods sequentially
  2. The last call (getUserById) is an internal method
  3. getUserById makes 3 external calls (to Logger and UserDAO)
  4. External calls are highlighted with [EXTERNAL]
  5. Depth indicators show nesting level

File Location Indicators

  • [EXTERNAL] - Third-party library, framework, or JDK call
  • [FileName.java] - Internal project method with source file name
  • ClassName.methodName(params) - Full method signature

Ordered List View

The same sequence in numbered format:

Call Sequence (Ordered List):
  1. newEmail.contains("@")
  2. user.setEmail(newEmail)
  3. UserDAO.update(user)
  4. [UserService.java] UserService.getUserById(userId)
    5. [EXTERNAL] Logger.info("Getting user...") (depth: 1)
    6. [EXTERNAL] UserDAO.findById(userId) (depth: 1)
    7. [EXTERNAL] Logger.warn("User not found") (depth: 1)

Use the ordered list to:

  • Understand execution order
  • Count total method calls
  • Identify performance bottlenecks

External API Calls Section

External API Calls:
  [EXT] Logger.info("Getting user...")
  [EXT] UserDAO.findById(userId)
  [EXT] NotificationService.send(...)

These are potential integration points that need:

  • Mocking in tests
  • Error handling
  • Performance monitoring
  • Circuit breakers (if remote services)

Exception Paths

Exception Paths:
  ! Throws: IllegalArgumentException
  ! Throws: Exception
  ! Catches: SQLException

Interpretation:

  • Throws: - Declared in method signature (throws Exception)
  • Throws: (in body) - Explicit throw new Exception() statements
  • Catches: - Try-catch blocks handling exceptions

Testing implications:

  • Test happy path AND exception paths
  • Verify exception messages
  • Test error recovery logic

πŸ“ Output Directory Structure

legacy-analyzer/
β”œβ”€β”€ legacy-cli                 # Unix/Linux/macOS executable
β”œβ”€β”€ legacy-cli.bat             # Windows batch file
β”œβ”€β”€ main.py                    # CLI entry point
β”œβ”€β”€ java_parser.py             # Java parser
β”œβ”€β”€ analyzer.py                # Code analyzer
β”œβ”€β”€ mock_generator.py          # Test generator
β”œβ”€β”€ api_analyzer.py            # API sequence analyzer
β”œβ”€β”€ output_formatter.py        # Console formatter
β”œβ”€β”€ api_output_formatter.py    # API formatter
β”œβ”€β”€ .gitignore                 # Git ignore
β”œβ”€β”€ examples/
β”‚   β”œβ”€β”€ UserService.java
β”‚   └── PaymentProcessor.java
β”œβ”€β”€ generated-tests/           # ← AUTO-CREATED
β”‚   └── UserServiceTest.java
└── api-reports/               # ← AUTO-CREATED
    └── api-analysis.md

Generated Directories:

  • generated-tests/ - All test files (git-ignored)
  • api-reports/ - All markdown reports (git-ignored)

Path Behavior:

  • Relative paths: Saved to auto-created subdirectories
  • Absolute paths: Saved to exact location specified
# Relative β†’ generated-tests/MyTest.java
./legacy-cli generate File.java --output MyTest.java

# Absolute β†’ /home/user/custom/MyTest.java
./legacy-cli generate File.java --output /home/user/custom/MyTest.java

πŸ’‘ Use Cases & Examples

Use Case 1: Adding Tests to Legacy Code

Scenario: You have a 500-line OrderService.java with no tests.

# Step 1: Analyze complexity
./legacy-cli analyze OrderService.java --verbose

# Step 2: Generate test scaffolding
./legacy-cli generate OrderService.java --output OrderServiceTest.java

# Step 3: Customize generated tests
# Edit generated-tests/OrderServiceTest.java
# Add specific assertions and mock behaviors

What you get:

  • Understanding of code complexity
  • Complete test class structure
  • Mock setup for all dependencies
  • Test stubs for all public methods

Use Case 2: Understanding API Flow

Scenario: You need to understand how processPayment works across multiple classes.

# Analyze the entire payment module
./legacy-cli api-analyze src/payment/ --export payment-api-flow.md

What you learn:

  • Which methods processPayment calls
  • Cross-class dependencies
  • External service integrations (PaymentGateway, Database)
  • Exception handling strategy

Example result:

processPayment()
β”œβ”€β”€ validateCard() [CardValidator.java]
β”‚   β”œβ”€β”€ [EXTERNAL] CardDatabase.lookup()
β”‚   └── [EXTERNAL] FraudService.check()
β”œβ”€β”€ [EXTERNAL] PaymentGateway.charge()
└── sendConfirmation() [NotificationService.java]
    β”œβ”€β”€ [EXTERNAL] EmailService.send()
    └── [EXTERNAL] SMSService.send()

Use Case 3: Refactoring with Confidence

Scenario: You want to refactor a complex method but need to understand its impact.

# Before refactoring
./legacy-cli api-analyze src/ --export before-refactor.md

# After refactoring
./legacy-cli api-analyze src/ --export after-refactor.md

# Compare the two markdown files to see changes

Benefits:

  • Document original behavior
  • Verify refactoring didn't change call sequences
  • Identify unintended side effects

Use Case 4: Code Review & Documentation

Scenario: Reviewing a PR that adds new APIs.

# Generate API documentation
./legacy-cli api-analyze src/ --export pr-123-api-changes.md

Use the report to:

  • Review method invocation patterns
  • Identify missing error handling
  • Spot potential performance issues
  • Document API contracts

πŸŽ“ Best Practices

For Mock Generation

  1. Always review generated tests - They're starting points, not complete tests
  2. Add specific assertions - Replace generic assertNotNull with business logic checks
  3. Mock external dependencies - Database, HTTP clients, file I/O
  4. Test edge cases - Null inputs, empty lists, boundary values
  5. Verify interactions - Use verify() to check method calls

Example customization:

// Generated (generic)
@Test
public void testGetUserById_Success() {
    when(userDAO.findById(1)).thenReturn(mock(User.class));
    User result = userService.getUserById(1);
    assertNotNull(result);
}

// Customized (specific)
@Test
public void testGetUserById_Success() {
    User mockUser = new User(1, "John", "john@example.com");
    when(userDAO.findById(1)).thenReturn(mockUser);

    User result = userService.getUserById(1);

    assertEquals(1, result.getId());
    assertEquals("John", result.getName());
    verify(userDAO, times(1)).findById(1);
}

For API Analysis

  1. Start with small modules - Analyze one package at a time
  2. Focus on complex methods - Methods with 20+ lines and deep nesting
  3. Document external dependencies - Note which need mocking/stubbing
  4. Track exception flows - Ensure all paths are tested
  5. Export to markdown - Keep reports in version control for historical reference

For Large Codebases

# Analyze by package
./legacy-cli api-analyze src/payment --export payment-apis.md
./legacy-cli api-analyze src/orders --export order-apis.md
./legacy-cli api-analyze src/users --export user-apis.md

# Use --summary for quick overview
./legacy-cli api-analyze src/ --summary

πŸ”§ Complexity Indicators

Method Complexity

  • [S] Simple (≀5 lines) - Easy to test
  • [M] Moderate (6-15 lines) - Needs good coverage
  • [C] Complex (>15 lines) - High priority for testing

Testability Score

  • 80-100 (Good) - Easy to test, well-structured
  • 60-79 (Fair) - Some improvements needed
  • 0-59 (Needs Improvement) - Difficult to test, refactoring recommended

Factors affecting score:

  • Constructor injection (+20 points)
  • Few dependencies (+10 points)
  • No static methods (+5 points)
  • Clear method signatures (+5 points)

πŸ› Troubleshooting

"No public APIs found"

  • Check that Java files have public methods
  • Ensure you're pointing to the correct directory
  • Verify files have .java extension

"Cannot parse Java file"

  • Ensure Java syntax is valid
  • Check for unusual annotations or syntax
  • File must contain a valid class declaration

Unicode/Encoding Errors

  • Tool uses ASCII-safe characters
  • Should work on all platforms
  • If issues persist, redirect output: ./legacy-cli api-analyze examples > output.txt

πŸ“š Additional Resources

Project Structure

legacy-analyzer/
β”œβ”€β”€ πŸ“„ README.md              ← You are here
β”œβ”€β”€ πŸ“„ CHANGELOG.md           ← Version history
β”œβ”€β”€ πŸ“„ QUICKSTART.md          ← 2-minute guide
β”œβ”€β”€ legacy-cli                ← Unix/Linux/macOS executable
β”œβ”€β”€ legacy-cli.bat            ← Windows executable
└── examples/                 ← Sample Java files

Example Files Provided

  • UserService.java - CRUD service with DAO pattern
  • PaymentProcessor.java - Complex business logic with external calls

Try them:

./legacy-cli analyze examples/UserService.java
./legacy-cli api-analyze examples

🀝 Contributing

Found a bug? Have a feature request?

  1. Check existing issues
  2. Create a new issue with details
  3. Include example Java files if applicable

πŸ“ License

This tool is provided as-is for analyzing and testing Java code.


⭐ Key Takeaways

  1. analyze - Understand single file complexity
  2. generate - Create test scaffolding quickly
  3. api-analyze - Map entire project API flows
  4. Tree View - Visualize method call hierarchy
  5. External Calls - Identify integration points
  6. Auto-organized - Files saved to clean directories

Start simple, analyze often, test thoroughly.


Built with ❀️ for testing legacy Java code

About

A powerful CLI tool that analyzes Java legacy code, generates Mockito test mocks, and maps API invocation sequences across your entire codebase.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •