Back to Repositories

Testing TCSH Shell Command Processing in TheFuck

A comprehensive test suite for the TCSH shell integration in the TheFuck project, verifying shell command handling, alias management, and configuration capabilities. The tests ensure proper interaction between the application and TCSH shell environment.

Test Coverage Overview

This test suite provides extensive coverage of TCSH shell functionality within TheFuck application:

  • Shell command transformation and interpretation
  • Alias management and configuration
  • History tracking and retrieval
  • Shell version detection and compatibility
  • Error handling and edge cases

Implementation Analysis

The testing approach utilizes pytest’s fixture-based architecture for efficient test setup and execution. The implementation leverages mocking to isolate shell interactions and ensures consistent test behavior across different environments.

  • Fixture-based test setup
  • Parametrized test cases for command transformation
  • Mock objects for shell command execution
  • Automated configuration verification

Technical Details

Testing infrastructure includes:

  • pytest framework with fixtures and parametrization
  • Mock objects for process execution
  • Shell command simulation
  • Version detection mechanisms
  • Configuration path validation

Best Practices Demonstrated

The test suite exemplifies several testing best practices:

  • Isolation of system dependencies
  • Comprehensive edge case coverage
  • Clear test case organization
  • Efficient test setup and teardown
  • Proper error handling validation

nvbn/thefuck

tests/shells/test_tcsh.py

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

import pytest
from thefuck.shells.tcsh import Tcsh


@pytest.mark.usefixtures('isfile', 'no_memoize', 'no_cache')
class TestTcsh(object):
    @pytest.fixture
    def shell(self):
        return Tcsh()

    @pytest.fixture(autouse=True)
    def Popen(self, mocker):
        mock = mocker.patch('thefuck.shells.tcsh.Popen')
        mock.return_value.stdout.read.return_value = (
            b'fuck\teval $(thefuck $(fc -ln -1))
'
            b'l\tls -CF
'
            b'la\tls -A
'
            b'll\tls -alF')
        return mock

    @pytest.mark.parametrize('before, after', [
        ('pwd', 'pwd'),
        ('fuck', 'eval $(thefuck $(fc -ln -1))'),
        ('awk', 'awk'),
        ('ll', 'ls -alF')])
    def test_from_shell(self, before, after, shell):
        assert shell.from_shell(before) == after

    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() == {'fuck': 'eval $(thefuck $(fc -ln -1))',
                                       'l': 'ls -CF',
                                       'la': 'ls -A',
                                       'll': 'ls -alF'}

    def test_app_alias(self, shell):
        assert 'setenv TF_SHELL tcsh' in shell.app_alias('fuck')
        assert 'alias fuck' in shell.app_alias('fuck')
        assert 'alias FUCK' in shell.app_alias('FUCK')
        assert 'thefuck' in shell.app_alias('fuck')

    def test_get_history(self, history_lines, shell):
        history_lines(['ls', 'rm'])
        assert list(shell.get_history()) == ['ls', 'rm']

    def test_how_to_configure(self, shell, config_exists):
        config_exists.return_value = True
        assert shell.how_to_configure().can_configure_automatically

    def test_how_to_configure_when_config_not_found(self, shell,
                                                    config_exists):
        config_exists.return_value = False
        assert not shell.how_to_configure().can_configure_automatically

    def test_info(self, shell, Popen):
        Popen.return_value.stdout.read.side_effect = [
            b'tcsh 6.20.00 (Astron) 2016-11-24 (unknown-unknown-bsd44) 
']
        assert shell.info() == 'Tcsh 6.20.00'
        assert Popen.call_args[0][0] == ['tcsh', '--version']

    @pytest.mark.parametrize('side_effect, exception', [
        ([b'
'], IndexError), (OSError, OSError)])
    def test_get_version_error(self, side_effect, exception, shell, Popen):
        Popen.return_value.stdout.read.side_effect = side_effect
        with pytest.raises(exception):
            shell._get_version()
        assert Popen.call_args[0][0] == ['tcsh', '--version']