Back to Repositories

Testing Generic Shell Command Processing in TheFuck

This test suite validates the Generic shell implementation in TheFuck project, covering basic shell operations and command handling. It ensures proper functionality of shell command processing, aliases, and history management within the generic shell context.

Test Coverage Overview

The test suite provides comprehensive coverage of Generic shell operations including:

  • Command processing and transformation
  • Shell operation handling (AND/OR operations)
  • Alias management and configuration
  • History tracking and command splitting
  • Version information retrieval and error handling

Implementation Analysis

The testing approach utilizes pytest fixtures and parametrized tests to validate Generic shell functionality. Tests follow a systematic pattern of validating shell command transformations, with specific focus on Unicode handling and command chaining behavior.

Key patterns include fixture-based shell instance creation and parametrized version information testing.

Technical Details

Testing tools and configuration:

  • pytest framework for test organization
  • Fixture-based test setup
  • Mock objects for version information testing
  • UTF-8 encoding validation
  • Parametrized test cases for different scenarios

Best Practices Demonstrated

The test suite demonstrates several testing best practices:

  • Isolated test cases with clear single-responsibility
  • Proper fixture usage for test setup
  • Comprehensive error case handling
  • Consistent test naming conventions
  • Effective use of pytest’s parametrize feature

nvbn/thefuck

tests/shells/test_generic.py

            
# -*- coding: utf-8 -*-

import pytest
from thefuck.shells import Generic


class TestGeneric(object):
    @pytest.fixture
    def shell(self):
        return Generic()

    def test_from_shell(self, shell):
        assert shell.from_shell('pwd') == 'pwd'

    def test_to_shell(self, shell):
        assert shell.to_shell('pwd') == 'pwd'

    def test_and_(self, shell):
        assert shell.and_('ls', 'cd') == 'ls && cd'

    def test_or_(self, shell):
        assert shell.or_('ls', 'cd') == 'ls || cd'

    def test_get_aliases(self, shell):
        assert shell.get_aliases() == {}

    def test_app_alias(self, shell):
        assert 'alias fuck' in shell.app_alias('fuck')
        assert 'alias FUCK' in shell.app_alias('FUCK')
        assert 'thefuck' in shell.app_alias('fuck')
        assert 'TF_ALIAS=fuck PYTHONIOENCODING' in shell.app_alias('fuck')
        assert 'PYTHONIOENCODING=utf-8 thefuck' in shell.app_alias('fuck')

    def test_get_history(self, history_lines, shell):
        history_lines(['ls', 'rm'])
        # We don't know what to do in generic shell with history lines,
        # so just ignore them:
        assert list(shell.get_history()) == []

    def test_split_command(self, shell):
        assert shell.split_command('ls') == ['ls']
        assert shell.split_command(u'echo café') == [u'echo', u'café']

    def test_how_to_configure(self, shell):
        assert shell.how_to_configure() is None

    @pytest.mark.parametrize('side_effect, expected_info, warn', [
        ([u'3.5.9'], u'Generic Shell 3.5.9', False),
        ([OSError], u'Generic Shell', True),
    ])
    def test_info(self, side_effect, expected_info, warn, shell, mocker):
        warn_mock = mocker.patch('thefuck.shells.generic.warn')
        shell._get_version = mocker.Mock(side_effect=side_effect)
        assert shell.info() == expected_info
        assert warn_mock.called is warn
        assert shell._get_version.called