1
0
mirror of https://github.com/nvbn/thefuck.git synced 2025-01-31 02:01:13 +00:00

Fix tests

This commit is contained in:
nvbn 2015-09-07 12:12:16 +03:00
parent 105d3d8137
commit 382eb8b86c
11 changed files with 91 additions and 95 deletions

View File

@ -1,5 +1,5 @@
import pytest import pytest
from mock import Mock from thefuck import conf
def pytest_addoption(parser): def pytest_addoption(parser):
@ -14,9 +14,15 @@ def no_memoize(monkeypatch):
monkeypatch.setattr('thefuck.utils.memoize.disabled', True) monkeypatch.setattr('thefuck.utils.memoize.disabled', True)
@pytest.fixture(autouse=True)
def settings(request):
request.addfinalizer(lambda: conf.settings.update(conf.DEFAULT_SETTINGS))
return conf.settings
@pytest.fixture @pytest.fixture
def settings(): def no_colors(settings):
return Mock(debug=False, no_colors=True) settings.no_colors = True
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)

View File

@ -26,22 +26,23 @@ def environ(monkeypatch):
@pytest.mark.usefixture('environ') @pytest.mark.usefixture('environ')
def test_settings_defaults(load_source): def test_settings_defaults(load_source, settings):
load_source.return_value = object() load_source.return_value = object()
conf.init_settings(Mock())
for key, val in conf.DEFAULT_SETTINGS.items(): for key, val in conf.DEFAULT_SETTINGS.items():
assert getattr(conf.init_settings(Mock()), key) == val assert getattr(settings, key) == val
@pytest.mark.usefixture('environ') @pytest.mark.usefixture('environ')
class TestSettingsFromFile(object): class TestSettingsFromFile(object):
def test_from_file(self, load_source): def test_from_file(self, load_source, settings):
load_source.return_value = Mock(rules=['test'], load_source.return_value = Mock(rules=['test'],
wait_command=10, wait_command=10,
require_confirmation=True, require_confirmation=True,
no_colors=True, no_colors=True,
priority={'vim': 100}, priority={'vim': 100},
exclude_rules=['git']) exclude_rules=['git'])
settings = conf.init_settings(Mock()) conf.init_settings(Mock())
assert settings.rules == ['test'] assert settings.rules == ['test']
assert settings.wait_command == 10 assert settings.wait_command == 10
assert settings.require_confirmation is True assert settings.require_confirmation is True
@ -49,26 +50,26 @@ class TestSettingsFromFile(object):
assert settings.priority == {'vim': 100} assert settings.priority == {'vim': 100}
assert settings.exclude_rules == ['git'] assert settings.exclude_rules == ['git']
def test_from_file_with_DEFAULT(self, load_source): def test_from_file_with_DEFAULT(self, load_source, settings):
load_source.return_value = Mock(rules=conf.DEFAULT_RULES + ['test'], load_source.return_value = Mock(rules=conf.DEFAULT_RULES + ['test'],
wait_command=10, wait_command=10,
exclude_rules=[], exclude_rules=[],
require_confirmation=True, require_confirmation=True,
no_colors=True) no_colors=True)
settings = conf.init_settings(Mock()) conf.init_settings(Mock())
assert settings.rules == conf.DEFAULT_RULES + ['test'] assert settings.rules == conf.DEFAULT_RULES + ['test']
@pytest.mark.usefixture('load_source') @pytest.mark.usefixture('load_source')
class TestSettingsFromEnv(object): class TestSettingsFromEnv(object):
def test_from_env(self, environ): def test_from_env(self, environ, settings):
environ.update({'THEFUCK_RULES': 'bash:lisp', environ.update({'THEFUCK_RULES': 'bash:lisp',
'THEFUCK_EXCLUDE_RULES': 'git:vim', 'THEFUCK_EXCLUDE_RULES': 'git:vim',
'THEFUCK_WAIT_COMMAND': '55', 'THEFUCK_WAIT_COMMAND': '55',
'THEFUCK_REQUIRE_CONFIRMATION': 'true', 'THEFUCK_REQUIRE_CONFIRMATION': 'true',
'THEFUCK_NO_COLORS': 'false', 'THEFUCK_NO_COLORS': 'false',
'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15'}) 'THEFUCK_PRIORITY': 'bash=10:lisp=wrong:vim=15'})
settings = conf.init_settings(Mock()) conf.init_settings(Mock())
assert settings.rules == ['bash', 'lisp'] assert settings.rules == ['bash', 'lisp']
assert settings.exclude_rules == ['git', 'vim'] assert settings.exclude_rules == ['git', 'vim']
assert settings.wait_command == 55 assert settings.wait_command == 55
@ -76,9 +77,9 @@ class TestSettingsFromEnv(object):
assert settings.no_colors is False assert settings.no_colors is False
assert settings.priority == {'bash': 10, 'vim': 15} assert settings.priority == {'bash': 10, 'vim': 15}
def test_from_env_with_DEFAULT(self, environ): def test_from_env_with_DEFAULT(self, environ, settings):
environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'}) environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})
settings = conf.init_settings(Mock()) conf.init_settings(Mock())
assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp'] assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp']

View File

@ -16,7 +16,7 @@ def test_load_rule(mocker):
enabled_by_default=True, enabled_by_default=True,
priority=900, priority=900,
requires_output=True)) requires_output=True))
assert corrector.load_rule(Path('/rules/bash.py'), settings=Mock(priority={})) \ assert corrector.load_rule(Path('/rules/bash.py')) \
== Rule('bash', match, get_new_command, priority=900) == Rule('bash', match, get_new_command, priority=900)
load_source.assert_called_once_with('bash', '/rules/bash.py') load_source.assert_called_once_with('bash', '/rules/bash.py')
@ -48,29 +48,30 @@ class TestGetRules(object):
(['git.py', 'bash.py'], ['git'], [], ['git']), (['git.py', 'bash.py'], ['git'], [], ['git']),
(['git.py', 'bash.py'], conf.DEFAULT_RULES, ['git'], ['bash']), (['git.py', 'bash.py'], conf.DEFAULT_RULES, ['git'], ['bash']),
(['git.py', 'bash.py'], ['git'], ['git'], [])]) (['git.py', 'bash.py'], ['git'], ['git'], [])])
def test_get_rules(self, glob, paths, conf_rules, exclude_rules, loaded_rules): def test_get_rules(self, glob, settings, paths, conf_rules, exclude_rules,
loaded_rules):
glob([PosixPath(path) for path in paths]) glob([PosixPath(path) for path in paths])
settings = Mock(rules=self._prepare_rules(conf_rules), settings.update(rules=self._prepare_rules(conf_rules),
priority={}, priority={},
exclude_rules=self._prepare_rules(exclude_rules)) exclude_rules=self._prepare_rules(exclude_rules))
rules = corrector.get_rules(Path('~'), settings) rules = corrector.get_rules(Path('~'))
self._compare_names(rules, loaded_rules) self._compare_names(rules, loaded_rules)
class TestIsRuleMatch(object): class TestIsRuleMatch(object):
def test_no_match(self, settings): def test_no_match(self):
assert not corrector.is_rule_match( assert not corrector.is_rule_match(
Command('ls'), Rule('', lambda *_: False), settings) Command('ls'), Rule('', lambda *_: False))
def test_match(self, settings): def test_match(self):
rule = Rule('', lambda x, _: x.script == 'cd ..') rule = Rule('', lambda x, _: x.script == 'cd ..')
assert corrector.is_rule_match(Command('cd ..'), rule, settings) assert corrector.is_rule_match(Command('cd ..'), rule)
def test_when_rule_failed(self, capsys, settings): @pytest.mark.usefixtures('no_colors')
def test_when_rule_failed(self, capsys):
rule = Rule('test', Mock(side_effect=OSError('Denied')), rule = Rule('test', Mock(side_effect=OSError('Denied')),
requires_output=False) requires_output=False)
assert not corrector.is_rule_match( assert not corrector.is_rule_match(Command('ls'), rule)
Command('ls'), rule, settings)
assert capsys.readouterr()[1].split('\n')[0] == '[WARN] Rule test:' assert capsys.readouterr()[1].split('\n')[0] == '[WARN] Rule test:'
@ -78,14 +79,14 @@ class TestMakeCorrectedCommands(object):
def test_with_rule_returns_list(self): def test_with_rule_returns_list(self):
rule = Rule(get_new_command=lambda x, _: [x.script + '!', x.script + '@'], rule = Rule(get_new_command=lambda x, _: [x.script + '!', x.script + '@'],
priority=100) priority=100)
assert list(make_corrected_commands(Command(script='test'), rule, None)) \ assert list(make_corrected_commands(Command(script='test'), rule)) \
== [CorrectedCommand(script='test!', priority=100), == [CorrectedCommand(script='test!', priority=100),
CorrectedCommand(script='test@', priority=200)] CorrectedCommand(script='test@', priority=200)]
def test_with_rule_returns_command(self): def test_with_rule_returns_command(self):
rule = Rule(get_new_command=lambda x, _: x.script + '!', rule = Rule(get_new_command=lambda x, _: x.script + '!',
priority=100) priority=100)
assert list(make_corrected_commands(Command(script='test'), rule, None)) \ assert list(make_corrected_commands(Command(script='test'), rule)) \
== [CorrectedCommand(script='test!', priority=100)] == [CorrectedCommand(script='test!', priority=100)]
def test_get_corrected_commands(mocker): def test_get_corrected_commands(mocker):
@ -97,5 +98,5 @@ def test_get_corrected_commands(mocker):
get_new_command=lambda x, _: [x.script + '@', x.script + ';'], get_new_command=lambda x, _: [x.script + '@', x.script + ';'],
priority=60)] priority=60)]
mocker.patch('thefuck.corrector.get_rules', return_value=rules) mocker.patch('thefuck.corrector.get_rules', return_value=rules)
assert [cmd.script for cmd in get_corrected_commands(command, None, Mock(debug=False))] \ assert [cmd.script for cmd in get_corrected_commands(command, None)] \
== ['test!', 'test@', 'test;'] == ['test!', 'test@', 'test;']

View File

@ -1,14 +1,20 @@
import pytest
from mock import Mock from mock import Mock
from thefuck import logs from thefuck import logs
def test_color(): def test_color(settings):
assert logs.color('red', Mock(no_colors=False)) == 'red' settings.no_colors = False
assert logs.color('red', Mock(no_colors=True)) == '' assert logs.color('red') == 'red'
settings.no_colors = True
assert logs.color('red') == ''
def test_debug(capsys): @pytest.mark.usefixtures('no_colors')
logs.debug('test', Mock(no_colors=True, debug=True)) @pytest.mark.parametrize('debug, stderr', [
assert capsys.readouterr() == ('', 'DEBUG: test\n') (True, 'DEBUG: test\n'),
logs.debug('test', Mock(no_colors=True, debug=False)) (False, '')])
assert capsys.readouterr() == ('', '') def test_debug(capsys, settings, debug, stderr):
settings.debug = debug
logs.debug('test')
assert capsys.readouterr() == ('', stderr)

View File

@ -24,9 +24,9 @@ class TestGetCommand(object):
monkeypatch.setattr('thefuck.shells.from_shell', lambda x: x) monkeypatch.setattr('thefuck.shells.from_shell', lambda x: x)
monkeypatch.setattr('thefuck.shells.to_shell', lambda x: x) monkeypatch.setattr('thefuck.shells.to_shell', lambda x: x)
def test_get_command_calls(self, Popen): def test_get_command_calls(self, Popen, settings):
assert main.get_command(Mock(env={}), settings.env = {}
['thefuck', 'apt-get', 'search', 'vim']) \ assert main.get_command(['thefuck', 'apt-get', 'search', 'vim']) \
== Command('apt-get search vim', 'stdout', 'stderr') == Command('apt-get search vim', 'stdout', 'stderr')
Popen.assert_called_once_with('apt-get search vim', Popen.assert_called_once_with('apt-get search vim',
shell=True, shell=True,
@ -41,6 +41,6 @@ class TestGetCommand(object):
(['thefuck', 'ls'], 'ls')]) (['thefuck', 'ls'], 'ls')])
def test_get_command_script(self, args, result): def test_get_command_script(self, args, result):
if result: if result:
assert main.get_command(Mock(env={}), args).script == result assert main.get_command(args).script == result
else: else:
assert main.get_command(Mock(env={}), args) is None assert main.get_command(args) is None

View File

@ -10,14 +10,6 @@ def test_rules_names_list():
assert Rule('bash') not in RulesNamesList(['lisp']) assert Rule('bash') not in RulesNamesList(['lisp'])
def test_update_settings():
settings = Settings({'key': 'val'})
new_settings = settings.update(key='new-val', unset='unset-value')
assert new_settings.key == 'val'
assert new_settings.unset == 'unset-value'
assert settings.key == 'val'
class TestSortedCorrectedCommandsSequence(object): class TestSortedCorrectedCommandsSequence(object):
def test_realises_generator_only_on_demand(self, settings): def test_realises_generator_only_on_demand(self, settings):
should_realise = False should_realise = False
@ -28,24 +20,23 @@ class TestSortedCorrectedCommandsSequence(object):
assert should_realise assert should_realise
yield CorrectedCommand('git checkout', priority=100) yield CorrectedCommand('git checkout', priority=100)
commands = SortedCorrectedCommandsSequence(gen(), settings) commands = SortedCorrectedCommandsSequence(gen())
assert commands[0] == CorrectedCommand('git commit') assert commands[0] == CorrectedCommand('git commit')
should_realise = True should_realise = True
assert commands[1] == CorrectedCommand('git checkout', priority=100) assert commands[1] == CorrectedCommand('git checkout', priority=100)
assert commands[2] == CorrectedCommand('git branch', priority=200) assert commands[2] == CorrectedCommand('git branch', priority=200)
def test_remove_duplicates(self, settings): def test_remove_duplicates(self):
side_effect = lambda *_: None side_effect = lambda *_: None
seq = SortedCorrectedCommandsSequence( seq = SortedCorrectedCommandsSequence(
iter([CorrectedCommand('ls', priority=100), iter([CorrectedCommand('ls', priority=100),
CorrectedCommand('ls', priority=200), CorrectedCommand('ls', priority=200),
CorrectedCommand('ls', side_effect, 300)]), CorrectedCommand('ls', side_effect, 300)]))
settings)
assert set(seq) == {CorrectedCommand('ls', priority=100), assert set(seq) == {CorrectedCommand('ls', priority=100),
CorrectedCommand('ls', side_effect, 300)} CorrectedCommand('ls', side_effect, 300)}
def test_with_blank(self, settings): def test_with_blank(self):
seq = SortedCorrectedCommandsSequence(iter([]), settings) seq = SortedCorrectedCommandsSequence(iter([]))
assert list(seq) == [] assert list(seq) == []

View File

@ -56,66 +56,55 @@ def test_command_selector():
assert changes == [1, 2, 3, 1, 3] assert changes == [1, 2, 3, 1, 3]
@pytest.mark.usefixtures('no_colors')
class TestSelectCommand(object): class TestSelectCommand(object):
@pytest.fixture @pytest.fixture
def commands_with_side_effect(self, settings): def commands_with_side_effect(self):
return SortedCorrectedCommandsSequence( return SortedCorrectedCommandsSequence(
iter([CorrectedCommand('ls', lambda *_: None, 100), iter([CorrectedCommand('ls', lambda *_: None, 100),
CorrectedCommand('cd', lambda *_: None, 100)]), CorrectedCommand('cd', lambda *_: None, 100)]))
settings)
@pytest.fixture @pytest.fixture
def commands(self, settings): def commands(self):
return SortedCorrectedCommandsSequence( return SortedCorrectedCommandsSequence(
iter([CorrectedCommand('ls', None, 100), iter([CorrectedCommand('ls', None, 100),
CorrectedCommand('cd', None, 100)]), CorrectedCommand('cd', None, 100)]))
settings)
def test_without_commands(self, capsys): def test_without_commands(self, capsys):
assert ui.select_command([], Mock(debug=False, no_color=True)) is None assert ui.select_command([]) is None
assert capsys.readouterr() == ('', 'No fucks given\n') assert capsys.readouterr() == ('', 'No fucks given\n')
def test_without_confirmation(self, capsys, commands): def test_without_confirmation(self, capsys, commands, settings):
assert ui.select_command(commands, settings.require_confirmation = False
Mock(debug=False, no_color=True, assert ui.select_command(commands) == commands[0]
require_confirmation=False)) == commands[0]
assert capsys.readouterr() == ('', 'ls\n') assert capsys.readouterr() == ('', 'ls\n')
def test_without_confirmation_with_side_effects(self, capsys, def test_without_confirmation_with_side_effects(
commands_with_side_effect): self, capsys, commands_with_side_effect, settings):
assert ui.select_command(commands_with_side_effect, settings.require_confirmation = False
Mock(debug=False, no_color=True, assert ui.select_command(commands_with_side_effect) \
require_confirmation=False)) \
== commands_with_side_effect[0] == commands_with_side_effect[0]
assert capsys.readouterr() == ('', 'ls (+side effect)\n') assert capsys.readouterr() == ('', 'ls (+side effect)\n')
def test_with_confirmation(self, capsys, patch_getch, commands): def test_with_confirmation(self, capsys, patch_getch, commands):
patch_getch(['\n']) patch_getch(['\n'])
assert ui.select_command(commands, assert ui.select_command(commands) == commands[0]
Mock(debug=False, no_color=True,
require_confirmation=True)) == commands[0]
assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\n') assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\n')
def test_with_confirmation_abort(self, capsys, patch_getch, commands): def test_with_confirmation_abort(self, capsys, patch_getch, commands):
patch_getch([KeyboardInterrupt]) patch_getch([KeyboardInterrupt])
assert ui.select_command(commands, assert ui.select_command(commands) is None
Mock(debug=False, no_color=True,
require_confirmation=True)) is None
assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\nAborted\n') assert capsys.readouterr() == ('', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\nAborted\n')
def test_with_confirmation_with_side_effct(self, capsys, patch_getch, def test_with_confirmation_with_side_effct(self, capsys, patch_getch,
commands_with_side_effect): commands_with_side_effect):
patch_getch(['\n']) patch_getch(['\n'])
assert ui.select_command(commands_with_side_effect, assert ui.select_command(commands_with_side_effect)\
Mock(debug=False, no_color=True,
require_confirmation=True))\
== commands_with_side_effect[0] == commands_with_side_effect[0]
assert capsys.readouterr() == ('', u'\x1b[1K\rls (+side effect) [enter/↑/↓/ctrl+c]\n') assert capsys.readouterr() == ('', u'\x1b[1K\rls (+side effect) [enter/↑/↓/ctrl+c]\n')
def test_with_confirmation_select_second(self, capsys, patch_getch, commands): def test_with_confirmation_select_second(self, capsys, patch_getch, commands):
patch_getch(['\x1b', '[', 'B', '\n']) patch_getch(['\x1b', '[', 'B', '\n'])
assert ui.select_command(commands, assert ui.select_command(commands) == commands[1]
Mock(debug=False, no_color=True,
require_confirmation=True)) == commands[1]
assert capsys.readouterr() == ( assert capsys.readouterr() == (
'', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\x1b[1K\rcd [enter/↑/↓/ctrl+c]\n') '', u'\x1b[1K\rls [enter/↑/↓/ctrl+c]\x1b[1K\rcd [enter/↑/↓/ctrl+c]\n')

View File

@ -1,7 +1,7 @@
import pytest import pytest
from mock import Mock from mock import Mock
import six import six
from thefuck.utils import wrap_settings, \ from thefuck.utils import default_settings, \
memoize, get_closest, get_all_executables, replace_argument, \ memoize, get_closest, get_all_executables, replace_argument, \
get_all_matched_commands, is_app, for_app, cache get_all_matched_commands, is_app, for_app, cache
from thefuck.types import Settings from thefuck.types import Settings
@ -12,9 +12,9 @@ from tests.utils import Command
({'key': 'val'}, {}, {'key': 'val'}), ({'key': 'val'}, {}, {'key': 'val'}),
({'key': 'new-val'}, {'key': 'val'}, {'key': 'val'}), ({'key': 'new-val'}, {'key': 'val'}, {'key': 'val'}),
({'key': 'new-val', 'unset': 'unset'}, {'key': 'val'}, {'key': 'val', 'unset': 'unset'})]) ({'key': 'new-val', 'unset': 'unset'}, {'key': 'val'}, {'key': 'val', 'unset': 'unset'})])
def test_wrap_settings(override, old, new): def test_default_settings(override, old, new):
fn = lambda _, settings: settings fn = lambda _, settings: settings
assert wrap_settings(override)(fn)(None, Settings(old)) == new assert default_settings(override)(fn)(None, Settings(old)) == new
def test_memoize(): def test_memoize():

View File

@ -13,11 +13,11 @@ def load_rule(rule):
rule_module = load_source(name, str(rule)) rule_module = load_source(name, str(rule))
priority = getattr(rule_module, 'priority', DEFAULT_PRIORITY) priority = getattr(rule_module, 'priority', DEFAULT_PRIORITY)
return Rule(name, rule_module.match, return Rule(name, rule_module.match,
rule_module.get_new_command, rule_module.get_new_command,
getattr(rule_module, 'enabled_by_default', True), getattr(rule_module, 'enabled_by_default', True),
getattr(rule_module, 'side_effect', None), getattr(rule_module, 'side_effect', None),
settings.priority.get(name, priority), settings.priority.get(name, priority),
getattr(rule_module, 'requires_output', True)) getattr(rule_module, 'requires_output', True))
def get_loaded_rules(rules): def get_loaded_rules(rules):

View File

@ -1,6 +1,6 @@
import re import re
import os import os
from thefuck.utils import memoize, wrap_settings from thefuck.utils import memoize, default_settings
from thefuck import shells from thefuck import shells
@ -57,7 +57,7 @@ def match(command, settings):
return _search(command.stderr) or _search(command.stdout) return _search(command.stderr) or _search(command.stdout)
@wrap_settings({'fixlinecmd': '{editor} {file} +{line}', @default_settings({'fixlinecmd': '{editor} {file} +{line}',
'fixcolcmd': None}) 'fixcolcmd': None})
def get_new_command(command, settings): def get_new_command(command, settings):
m = _search(command.stderr) or _search(command.stdout) m = _search(command.stderr) or _search(command.stdout)

View File

@ -60,18 +60,20 @@ def which(program):
return None return None
def wrap_settings(params): def default_settings(params):
"""Adds default values to settings if it not presented. """Adds default values to settings if it not presented.
Usage: Usage:
@wrap_settings({'apt': '/usr/bin/apt'}) @default_settings({'apt': '/usr/bin/apt'})
def match(command, settings): def match(command, settings):
print(settings.apt) print(settings.apt)
""" """
def _wrap_settings(fn, command, settings): def _wrap_settings(fn, command, settings):
return fn(command, Settings(settings, **params)) for k, w in params.items():
settings.setdefault(k, w)
return fn(command, settings)
return decorator(_wrap_settings) return decorator(_wrap_settings)