Back to Repositories

Testing Command Correction Algorithm in TheFuck

This test suite verifies the functionality of the ‘no_command’ rule in TheFuck, which handles command not found errors by suggesting similar valid commands. The tests ensure proper command matching and correction behavior across different shell environments.

Test Coverage Overview

The test suite provides comprehensive coverage of command matching and suggestion logic, focusing on common command typos and shell errors. Key test scenarios include:

  • Command not found error patterns across different shells
  • Similar command suggestions based on available executables
  • Command history integration for contextual suggestions
  • Edge cases with various command typos and formats

Implementation Analysis

The testing approach utilizes pytest fixtures and parametrized tests to efficiently verify command correction behavior. The implementation employs mocking to control environment variables and command availability, with specific focus on:

  • Fixture-based executable command mocking
  • Parametrized test cases for different command patterns
  • History integration testing
  • Command matching algorithm verification

Technical Details

Testing infrastructure includes:

  • pytest framework with fixture automation
  • Mock objects for system command simulation
  • Parametrized test decorators for multiple test cases
  • Command class integration for shell interaction testing

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Comprehensive fixture usage for test setup
  • Clear separation of matching and command generation tests
  • Extensive use of parametrization for thorough coverage
  • Proper mocking of system dependencies
  • Clean test organization with focused test methods

nvbn/thefuck

tests/rules/test_no_command.py

            
import pytest
from thefuck.rules.no_command import match, get_new_command
from thefuck.types import Command


@pytest.fixture(autouse=True)
def get_all_executables(mocker):
    mocker.patch('thefuck.rules.no_command.get_all_executables',
                 return_value=['vim', 'fsck', 'git', 'go', 'python'])


@pytest.fixture(autouse=True)
def history_without_current(mocker):
    return mocker.patch(
        'thefuck.rules.no_command.get_valid_history_without_current',
        return_value=['git commit'])


@pytest.mark.usefixtures('no_memoize')
@pytest.mark.parametrize('script, output', [
    ('vom file.py', 'vom: not found'),
    ('fucck', 'fucck: not found'),
    ('puthon', "'puthon' is not recognized as an internal or external command"),
    ('got commit', 'got: command not found'),
    ('gti commit -m "new commit"', 'gti: command not found')])
def test_match(mocker, script, output):
    mocker.patch('thefuck.rules.no_command.which', return_value=None)

    assert match(Command(script, output))


@pytest.mark.usefixtures('no_memoize')
@pytest.mark.parametrize('script, output, which', [
    ('qweqwe', 'qweqwe: not found', None),
    ('vom file.py', 'some text', None),
    ('vim file.py', 'vim: not found', 'vim')])
def test_not_match(mocker, script, output, which):
    mocker.patch('thefuck.rules.no_command.which', return_value=which)

    assert not match(Command(script, output))


@pytest.mark.usefixtures('no_memoize')
@pytest.mark.parametrize('script, result', [
    ('vom file.py', ['vim file.py']),
    ('fucck', ['fsck']),
    ('got commit', ['git commit', 'go commit']),
    ('gti commit -m "new commit"', ['git commit -m "new commit"'])])
def test_get_new_command(script, result):
    assert get_new_command(Command(script, '')) == result