Back to Repositories

Testing Zsh Shell Command Processing in thefuck

This test suite validates the Zsh shell integration functionality in the ‘thefuck’ command-line tool, focusing on command correction and alias handling. The tests ensure proper shell command parsing, alias management, and environment configuration for Zsh-specific implementations.

Test Coverage Overview

The test suite provides comprehensive coverage of Zsh shell functionality:

  • Command translation and shell conversion testing
  • Alias management and configuration verification
  • Shell history access and parsing
  • Environment variable handling and version detection
  • Error handling for shell operations

Implementation Analysis

The testing approach utilizes pytest fixtures and parametrized tests to validate Zsh shell interactions. The implementation employs mocking strategies for system calls and file operations, with particular attention to shell-specific command parsing and environment configuration patterns.

Key testing patterns include fixture-based setup, command string manipulation verification, and shell environment simulation.

Technical Details

Testing tools and configuration:

  • pytest framework with fixture decorators
  • Mock objects for process handling (Popen)
  • Environment variable manipulation
  • Shell command simulation
  • Version detection mechanisms

Best Practices Demonstrated

The test suite exemplifies several testing best practices in Python:

  • Proper test isolation using fixtures
  • Parametrized testing for multiple scenarios
  • Mocking of system resources
  • Clear test case organization
  • Comprehensive edge case handling

nvbn/thefuck

tests/shells/test_zsh.py

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

import os
import pytest
from thefuck.shells.zsh import Zsh


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

    @pytest.fixture(autouse=True)
    def Popen(self, mocker):
        mock = mocker.patch('thefuck.shells.zsh.Popen')
        return mock

    @pytest.fixture(autouse=True)
    def shell_aliases(self):
        os.environ['TF_SHELL_ALIASES'] = (
            'fuck=\'eval $(thefuck $(fc -ln -1 | tail -n 1))\'
'
            'l=\'ls -CF\'
'
            'la=\'ls -A\'
'
            'll=\'ls -alF\'')

    @pytest.mark.parametrize('before, after', [
        ('fuck', 'eval $(thefuck $(fc -ln -1 | tail -n 1))'),
        ('pwd', 'pwd'),
        ('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 | tail -n 1))',
            'l': 'ls -CF',
            'la': 'ls -A',
            'll': 'ls -alF'}

    def test_app_alias(self, shell):
        assert 'fuck () {' in shell.app_alias('fuck')
        assert 'FUCK () {' in shell.app_alias('FUCK')
        assert 'thefuck' in shell.app_alias('fuck')
        assert 'PYTHONIOENCODING' in shell.app_alias('fuck')

    def test_app_alias_variables_correctly_set(self, shell):
        alias = shell.app_alias('fuck')
        assert "fuck () {" in alias
        assert 'TF_SHELL=zsh' in alias
        assert "TF_ALIAS=fuck" in alias
        assert 'PYTHONIOENCODING=utf-8' in alias
        assert 'TF_SHELL_ALIASES=$(alias)' in alias

    def test_get_history(self, history_lines, shell):
        history_lines([': 1432613911:0;ls', ': 1432613916:0;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'3.5.9']
        assert shell.info() == 'ZSH 3.5.9'

    def test_get_version_error(self, shell, Popen):
        Popen.return_value.stdout.read.side_effect = OSError
        with pytest.raises(OSError):
            shell._get_version()
        assert Popen.call_args[0][0] == ['zsh', '-c', 'echo $ZSH_VERSION']