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

Refine tests

This commit is contained in:
nvbn 2015-05-02 04:29:55 +02:00
parent ba601644d6
commit dd1861955c
4 changed files with 237 additions and 191 deletions

View File

@ -1,89 +1,100 @@
import pytest
import six import six
from mock import patch, Mock from mock import Mock
from thefuck import conf from thefuck import conf
from tests.utils import Rule from tests.utils import Rule
def test_default(): @pytest.mark.parametrize('enabled, rules, result', [
assert Rule('test', enabled_by_default=True) in conf.DEFAULT_RULES (True, conf.DEFAULT_RULES, True),
assert Rule('test', enabled_by_default=False) not in conf.DEFAULT_RULES (False, conf.DEFAULT_RULES, False),
assert Rule('test', enabled_by_default=False) in (conf.DEFAULT_RULES + ['test']) (False, conf.DEFAULT_RULES + ['test'], True)])
def test_default(enabled, rules, result):
assert (Rule('test', enabled_by_default=enabled) in rules) == result
def test_settings_defaults(): @pytest.fixture
with patch('thefuck.conf.load_source', return_value=object()), \ def load_source(monkeypatch):
patch('thefuck.conf.os.environ', new_callable=lambda: {}): mock = Mock()
for key, val in conf.DEFAULT_SETTINGS.items(): monkeypatch.setattr('thefuck.conf.load_source', mock)
assert getattr(conf.get_settings(Mock()), key) == val return mock
def test_settings_from_file(): @pytest.fixture
with patch('thefuck.conf.load_source', return_value=Mock(rules=['test'], def environ(monkeypatch):
wait_command=10, data = {}
require_confirmation=True, monkeypatch.setattr('thefuck.conf.os.environ', data)
no_colors=True)), \ return data
patch('thefuck.conf.os.environ', new_callable=lambda: {}):
@pytest.mark.usefixture('environ')
def test_settings_defaults(load_source):
load_source.return_value = object()
for key, val in conf.DEFAULT_SETTINGS.items():
assert getattr(conf.get_settings(Mock()), key) == val
@pytest.mark.usefixture('environ')
class TestSettingsFromFile(object):
def test_from_file(self, load_source):
load_source.return_value = Mock(rules=['test'],
wait_command=10,
require_confirmation=True,
no_colors=True)
settings = conf.get_settings(Mock()) settings = conf.get_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
assert settings.no_colors is True assert settings.no_colors is True
def test_from_file_with_DEFAULT(self, load_source):
def test_settings_from_file_with_DEFAULT(): load_source.return_value = Mock(rules=conf.DEFAULT_RULES + ['test'],
with patch('thefuck.conf.load_source', return_value=Mock(rules=conf.DEFAULT_RULES + ['test'], wait_command=10,
wait_command=10, require_confirmation=True,
require_confirmation=True, no_colors=True)
no_colors=True)), \
patch('thefuck.conf.os.environ', new_callable=lambda: {}):
settings = conf.get_settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == conf.DEFAULT_RULES + ['test'] assert settings.rules == conf.DEFAULT_RULES + ['test']
def test_settings_from_env(): @pytest.mark.usefixture('load_source')
with patch('thefuck.conf.load_source', return_value=Mock(rules=['test'], class TestSettingsFromEnv(object):
wait_command=10)), \ def test_from_env(self, environ):
patch('thefuck.conf.os.environ', environ.update({'THEFUCK_RULES': 'bash:lisp',
new_callable=lambda: {'THEFUCK_RULES': 'bash:lisp', 'THEFUCK_WAIT_COMMAND': '55',
'THEFUCK_WAIT_COMMAND': '55', 'THEFUCK_REQUIRE_CONFIRMATION': 'true',
'THEFUCK_REQUIRE_CONFIRMATION': 'true', 'THEFUCK_NO_COLORS': 'false'})
'THEFUCK_NO_COLORS': 'false'}):
settings = conf.get_settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == ['bash', 'lisp'] assert settings.rules == ['bash', 'lisp']
assert settings.wait_command == 55 assert settings.wait_command == 55
assert settings.require_confirmation is True assert settings.require_confirmation is True
assert settings.no_colors is False assert settings.no_colors is False
def test_from_env_with_DEFAULT(self, environ):
def test_settings_from_env_with_DEFAULT(): environ.update({'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'})
with patch('thefuck.conf.load_source', return_value=Mock()), \
patch('thefuck.conf.os.environ', new_callable=lambda: {'THEFUCK_RULES': 'DEFAULT_RULES:bash:lisp'}):
settings = conf.get_settings(Mock()) settings = conf.get_settings(Mock())
assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp'] assert settings.rules == conf.DEFAULT_RULES + ['bash', 'lisp']
def test_initialize_settings_file_ignore_if_exists(): class TestInitializeSettingsFile(object):
settings_path_mock = Mock(is_file=Mock(return_value=True), open=Mock()) def test_ignore_if_exists(self):
user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock)) settings_path_mock = Mock(is_file=Mock(return_value=True), open=Mock())
conf.initialize_settings_file(user_dir_mock) user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock))
assert settings_path_mock.is_file.call_count == 1 conf.initialize_settings_file(user_dir_mock)
assert not settings_path_mock.open.called assert settings_path_mock.is_file.call_count == 1
assert not settings_path_mock.open.called
def test_create_if_doesnt_exists(self):
def test_initialize_settings_file_create_if_exists_not(): settings_file = six.StringIO()
settings_file = six.StringIO() settings_path_mock = Mock(
settings_path_mock = Mock( is_file=Mock(return_value=False),
is_file=Mock(return_value=False), open=Mock(return_value=Mock(
open=Mock(return_value=Mock( __exit__=lambda *args: None, __enter__=lambda *args: settings_file)))
__exit__=lambda *args: None, __enter__=lambda *args: settings_file user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock))
)), conf.initialize_settings_file(user_dir_mock)
) settings_file_contents = settings_file.getvalue()
user_dir_mock = Mock(joinpath=Mock(return_value=settings_path_mock)) assert settings_path_mock.is_file.call_count == 1
conf.initialize_settings_file(user_dir_mock) assert settings_path_mock.open.call_count == 1
settings_file_contents = settings_file.getvalue() assert conf.SETTINGS_HEADER in settings_file_contents
assert settings_path_mock.is_file.call_count == 1 for setting in conf.DEFAULT_SETTINGS.items():
assert settings_path_mock.open.call_count == 1 assert '# {} = {}\n'.format(*setting) in settings_file_contents
assert conf.SETTINGS_HEADER in settings_file_contents settings_file.close()
for setting in conf.DEFAULT_SETTINGS.items():
assert '# {} = {}\n'.format(*setting) in settings_file_contents
settings_file.close()

View File

@ -1,32 +1,30 @@
import pytest import pytest
from mock import patch, Mock from mock import Mock
from thefuck.history import History from thefuck.history import History
@pytest.fixture
def process(monkeypatch):
Process = Mock()
Process.return_value.parent.return_value.pid = 1
monkeypatch.setattr('thefuck.history.Process', Process)
@pytest.fixture
def db(monkeypatch):
class DBMock(dict):
def __init__(self):
super(DBMock, self).__init__()
self.sync = Mock()
def __call__(self, *args, **kwargs):
return self
db = DBMock()
monkeypatch.setattr('thefuck.history.shelve.open', db)
return db
@pytest.mark.usefixtures('process')
class TestHistory(object): class TestHistory(object):
@pytest.fixture(autouse=True)
def process(self, monkeypatch):
Process = Mock()
Process.return_value.parent.return_value.pid = 1
monkeypatch.setattr('thefuck.history.Process', Process)
return Process
@pytest.fixture(autouse=True)
def db(self, monkeypatch):
class DBMock(dict):
def __init__(self):
super(DBMock, self).__init__()
self.sync = Mock()
def __call__(self, *args, **kwargs):
return self
db = DBMock()
monkeypatch.setattr('thefuck.history.shelve.open', db)
return db
def test_set(self, db): def test_set(self, db):
history = History() history = History()
history.update(last_script='ls', history.update(last_script='ls',
@ -39,6 +37,6 @@ class TestHistory(object):
db['1-last_script'] = 'cd ..' db['1-last_script'] = 'cd ..'
assert history.last_script == 'cd ..' assert history.last_script == 'cd ..'
def test_get_without_value(self, db): def test_get_without_value(self):
history = History() history = History()
assert history.last_script is None assert history.last_script is None

View File

@ -1,51 +1,56 @@
import pytest
from subprocess import PIPE from subprocess import PIPE
from pathlib import PosixPath, Path from pathlib import PosixPath, Path
from mock import patch, Mock from mock import Mock
from thefuck import main, conf, types from thefuck import main, conf, types
from tests.utils import Rule, Command from tests.utils import Rule, Command
def test_load_rule(): def test_load_rule(monkeypatch):
match = object() match = object()
get_new_command = object() get_new_command = object()
with patch('thefuck.main.load_source', load_source = Mock()
return_value=Mock( load_source.return_value = Mock(match=match,
match=match, get_new_command=get_new_command,
get_new_command=get_new_command, enabled_by_default=True)
enabled_by_default=True)) as load_source: monkeypatch.setattr('thefuck.main.load_source', load_source)
assert main.load_rule(Path('/rules/bash.py')) \ assert main.load_rule(Path('/rules/bash.py')) \
== Rule('bash', match, get_new_command) == Rule('bash', match, get_new_command)
load_source.assert_called_once_with('bash', '/rules/bash.py') load_source.assert_called_once_with('bash', '/rules/bash.py')
def test_get_rules(): @pytest.mark.parametrize('conf_rules, rules', [
with patch('thefuck.main.Path.glob') as glob, \ (conf.DEFAULT_RULES, [Rule('bash', 'bash', 'bash'),
patch('thefuck.main.load_source', Rule('lisp', 'lisp', 'lisp'),
lambda x, _: Mock(match=x, get_new_command=x, Rule('bash', 'bash', 'bash'),
enabled_by_default=True)): Rule('lisp', 'lisp', 'lisp')]),
glob.return_value = [PosixPath('bash.py'), PosixPath('lisp.py')] (types.RulesNamesList(['bash']), [Rule('bash', 'bash', 'bash'),
assert list(main.get_rules( Rule('bash', 'bash', 'bash')])])
Path('~'), def test_get_rules(monkeypatch, conf_rules, rules):
Mock(rules=conf.DEFAULT_RULES))) \ monkeypatch.setattr(
== [Rule('bash', 'bash', 'bash'), 'thefuck.main.Path.glob',
Rule('lisp', 'lisp', 'lisp'), lambda *_: [PosixPath('bash.py'), PosixPath('lisp.py')])
Rule('bash', 'bash', 'bash'), monkeypatch.setattr('thefuck.main.load_source',
Rule('lisp', 'lisp', 'lisp')] lambda x, _: Mock(match=x, get_new_command=x,
assert list(main.get_rules( enabled_by_default=True))
Path('~'), assert list(main.get_rules(Path('~'), Mock(rules=conf_rules))) == rules
Mock(rules=types.RulesNamesList(['bash'])))) \
== [Rule('bash', 'bash', 'bash'),
Rule('bash', 'bash', 'bash')]
def test_get_command(): class TestGetCommand(object):
with patch('thefuck.main.Popen') as Popen, \ @pytest.fixture(autouse=True)
patch('thefuck.main.os.environ', def Popen(self, monkeypatch):
new_callable=lambda: {}), \ Popen = Mock()
patch('thefuck.main.wait_output',
return_value=True):
Popen.return_value.stdout.read.return_value = b'stdout' Popen.return_value.stdout.read.return_value = b'stdout'
Popen.return_value.stderr.read.return_value = b'stderr' Popen.return_value.stderr.read.return_value = b'stderr'
monkeypatch.setattr('thefuck.main.Popen', Popen)
return Popen
@pytest.fixture(autouse=True)
def prepare(self, monkeypatch):
monkeypatch.setattr('thefuck.main.os.environ', {})
monkeypatch.setattr('thefuck.main.wait_output', lambda *_: True)
def test_get_command_calls(self, Popen):
assert main.get_command(Mock(), Mock(), assert main.get_command(Mock(), Mock(),
['thefuck', 'apt-get', 'search', 'vim']) \ ['thefuck', 'apt-get', 'search', 'vim']) \
== Command('apt-get search vim', 'stdout', 'stderr') == Command('apt-get search vim', 'stdout', 'stderr')
@ -54,81 +59,113 @@ def test_get_command():
stdout=PIPE, stdout=PIPE,
stderr=PIPE, stderr=PIPE,
env={'LANG': 'C'}) env={'LANG': 'C'})
assert main.get_command(Mock(), Mock(), ['']) is None
# When command is `fuck`: @pytest.mark.parametrize('history, args, result', [
assert main.get_command( (Mock(), [''], None),
Mock(), (Mock(last_script='ls', last_fixed_script='ls -la'),
Mock(last_script='ls', last_fixed_script='ls -la'), ['thefuck', 'fuck'], 'ls -la'),
['thefuck', 'fuck']).script == 'ls -la' (Mock(last_script='ls', last_fixed_script='ls -la'),
# When command equals to last command: ['thefuck', 'ls'], 'ls -la'),
assert main.get_command( (Mock(last_script='ls', last_fixed_script=''),
Mock(), ['thefuck', 'ls'], 'ls'),
Mock(last_script='ls', last_fixed_script='ls -la'), (Mock(last_script='ls', last_fixed_script=''),
['thefuck', 'ls']).script == 'ls -la' ['thefuck', 'fuck'], 'ls')])
# When last command is `fuck` and no last fixed script: def test_get_command_script(self, history, args, result):
assert main.get_command( if result:
Mock(), assert main.get_command(Mock(), history, args).script == result
Mock(last_script='ls', last_fixed_script=''), else:
['thefuck', 'ls']).script == 'ls' assert main.get_command(Mock(), history, args) is None
def test_get_matched_rule(capsys): class TestGetMatchedRule(object):
rules = [Rule('', lambda x, _: x.script == 'cd ..'), @pytest.fixture
Rule('', lambda *_: False), def rules(self):
Rule('rule', Mock(side_effect=OSError('Denied')))] return [Rule('', lambda x, _: x.script == 'cd ..'),
assert main.get_matched_rule(Command('ls'), Rule('', lambda *_: False),
rules, Mock(no_colors=True)) is None Rule('rule', Mock(side_effect=OSError('Denied')))]
assert main.get_matched_rule(Command('cd ..'),
rules, Mock(no_colors=True)) == rules[0] def test_no_match(self):
assert capsys.readouterr()[1].split('\n')[0] \ assert main.get_matched_rule(
== '[WARN] Rule rule:' Command('ls'), [Rule('', lambda *_: False)],
Mock(no_colors=True)) is None
def test_match(self):
rule = Rule('', lambda x, _: x.script == 'cd ..')
assert main.get_matched_rule(
Command('cd ..'), [rule], Mock(no_colors=True)) == rule
def test_when_rule_failed(self, capsys):
main.get_matched_rule(
Command('ls'), [Rule('test', Mock(side_effect=OSError('Denied')))],
Mock(no_colors=True))
assert capsys.readouterr()[1].split('\n')[0] == '[WARN] Rule test:'
def test_run_rule(capsys): class TestRunRule(object):
with patch('thefuck.main.confirm', return_value=True): @pytest.fixture(autouse=True)
def confirm(self, monkeypatch):
mock = Mock(return_value=True)
monkeypatch.setattr('thefuck.main.confirm', mock)
return mock
def test_run_rule(self, capsys):
main.run_rule(Rule(get_new_command=lambda *_: 'new-command'), main.run_rule(Rule(get_new_command=lambda *_: 'new-command'),
Command(), Mock(), None) Command(), Mock(), None)
assert capsys.readouterr() == ('new-command\n', '') assert capsys.readouterr() == ('new-command\n', '')
# With side effect:
def test_run_rule_with_side_effect(self, capsys):
side_effect = Mock() side_effect = Mock()
settings = Mock() settings = Mock()
command = Mock(script='ls') command = Command()
history = Mock()
main.run_rule(Rule(get_new_command=lambda *_: 'new-command', main.run_rule(Rule(get_new_command=lambda *_: 'new-command',
side_effect=side_effect), side_effect=side_effect),
command, history, settings) command, Mock(), settings)
assert capsys.readouterr() == ('new-command\n', '') assert capsys.readouterr() == ('new-command\n', '')
side_effect.assert_called_once_with(command, settings) side_effect.assert_called_once_with(command, settings)
# Ensure that history updated:
def test_hisotry_updated(self):
history = Mock()
main.run_rule(Rule(get_new_command=lambda *_: 'ls -lah'),
Command('ls'), history, None)
history.update.assert_called_once_with(last_script='ls', history.update.assert_called_once_with(last_script='ls',
last_fixed_script='new-command') last_fixed_script='ls -lah')
with patch('thefuck.main.confirm', return_value=False):
def test_when_not_comfirmed(self, capsys, confirm):
confirm.return_value = False
main.run_rule(Rule(get_new_command=lambda *_: 'new-command'), main.run_rule(Rule(get_new_command=lambda *_: 'new-command'),
Command(), Mock(), None) Command(), Mock(), None)
assert capsys.readouterr() == ('', '') assert capsys.readouterr() == ('', '')
def test_confirm(capsys): class TestConfirm(object):
# When confirmation not required: @pytest.fixture
assert main.confirm('command', None, Mock(require_confirmation=False)) def stdin(self, monkeypatch):
assert capsys.readouterr() == ('', 'command\n') mock = Mock(return_value='\n')
# With side effect and without confirmation: monkeypatch.setattr('sys.stdin.read', mock)
assert main.confirm('command', Mock(), Mock(require_confirmation=False)) return mock
assert capsys.readouterr() == ('', 'command*\n')
# When confirmation required and confirmed: def test_when_not_required(self, capsys):
with patch('thefuck.main.sys.stdin.read', return_value='\n'): assert main.confirm('command', None, Mock(require_confirmation=False))
assert main.confirm( assert capsys.readouterr() == ('', 'command\n')
'command', None, Mock(require_confirmation=True,
no_colors=True)) def test_with_side_effect_and_without_confirmation(self, capsys):
assert main.confirm('command', Mock(), Mock(require_confirmation=False))
assert capsys.readouterr() == ('', 'command*\n')
# `stdin` fixture should be applied after `capsys`
def test_when_confirmation_required_and_confirmed(self, capsys, stdin):
assert main.confirm('command', None, Mock(require_confirmation=True,
no_colors=True))
assert capsys.readouterr() == ('', 'command [enter/ctrl+c]') assert capsys.readouterr() == ('', 'command [enter/ctrl+c]')
# With side effect:
assert main.confirm( # `stdin` fixture should be applied after `capsys`
'command', Mock(), Mock(require_confirmation=True, def test_when_confirmation_required_and_confirmed_with_side_effect(self, capsys, stdin):
no_colors=True)) assert main.confirm('command', Mock(), Mock(require_confirmation=True,
no_colors=True))
assert capsys.readouterr() == ('', 'command* [enter/ctrl+c]') assert capsys.readouterr() == ('', 'command* [enter/ctrl+c]')
# When confirmation required and ctrl+c:
with patch('thefuck.main.sys.stdin.read', side_effect=KeyboardInterrupt): def test_when_confirmation_required_and_aborted(self, capsys, stdin):
assert not main.confirm('command', None, stdin.side_effect = KeyboardInterrupt
Mock(require_confirmation=True, assert not main.confirm('command', None, Mock(require_confirmation=True,
no_colors=True)) no_colors=True))
assert capsys.readouterr() == ('', 'command [enter/ctrl+c]Aborted\n') assert capsys.readouterr() == ('', 'command [enter/ctrl+c]Aborted\n')

View File

@ -1,26 +1,26 @@
import pytest
from mock import Mock from mock import Mock
from thefuck.utils import sudo_support, wrap_settings from thefuck.utils import sudo_support, wrap_settings
from thefuck.types import Settings from thefuck.types import Settings
from tests.utils import Command from tests.utils import Command
def test_wrap_settings(): @pytest.mark.parametrize('override, old, new', [
({'key': 'val'}, {}, {'key': 'val'}),
({'key': 'new-val'}, {'key': 'val'}, {'key': 'new-val'})])
def test_wrap_settings(override, old, new):
fn = lambda _, settings: settings fn = lambda _, settings: settings
assert wrap_settings({'key': 'val'})(fn)(None, Settings({})) \ assert wrap_settings(override)(fn)(None, Settings(old)) == new
== {'key': 'val'}
assert wrap_settings({'key': 'new-val'})(fn)(
None, Settings({'key': 'val'})) == {'key': 'new-val'}
def test_sudo_support(): @pytest.mark.parametrize('return_value, command, called, result', [
fn = Mock(return_value=True, __name__='') ('ls -lah', 'sudo ls', 'ls', 'sudo ls -lah'),
assert sudo_support(fn)(Command('sudo ls'), None) ('ls -lah', 'ls', 'ls', 'ls -lah'),
fn.assert_called_once_with(Command('ls'), None) (True, 'sudo ls', 'ls', True),
(True, 'ls', 'ls', True),
fn.return_value = False (False, 'sudo ls', 'ls', False),
assert not sudo_support(fn)(Command('sudo ls'), None) (False, 'ls', 'ls', False)])
def test_sudo_support(return_value, command, called, result):
fn.return_value = 'pwd' fn = Mock(return_value=return_value, __name__='')
assert sudo_support(fn)(Command('sudo ls'), None) == 'sudo pwd' assert sudo_support(fn)(Command(command), None) == result
fn.assert_called_once_with(Command(called), None)
assert sudo_support(fn)(Command('ls'), None) == 'pwd'