Created
January 10, 2010 12:58
-
-
Save bebraw/273491 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from file import PluginDirectory | |
from interpreter import Interpreter | |
from plugin_loader import PluginLoader | |
class Application: | |
def run(self): | |
plugin_loader = PluginLoader() | |
plugin_directory = PluginDirectory() | |
commands = plugin_loader.load(plugin_directory) | |
interpreter = Interpreter(commands) | |
try: | |
while True: | |
input = self.input() | |
result = interpreter.interpret(input) | |
if result is not None: | |
self.output(result) | |
except SystemExit: | |
pass | |
def input(self): | |
return raw_input('>>> ') | |
def output(self, result): | |
print result |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from collections import deque | |
class InputError(Exception): | |
pass | |
class MatchError(Exception): | |
pass | |
class OutputError(Exception): | |
pass | |
class Line: | |
def __init__(self, content): | |
self.content = content | |
def __str__(self): | |
return self.content | |
class Input(Line): | |
pass | |
class Output(Line): | |
pass | |
def parse_line(line): | |
if len(line.strip()) == 0: | |
return | |
prefix = '>>> ' | |
if line.startswith(prefix): | |
content = line.strip(prefix) | |
return Input(content) | |
else: | |
content = line | |
return Output(content) | |
class ScenarioTester: | |
def __init__(self, app_class): | |
self.app = app_class() | |
self.app.input = self._input | |
self.app.output = self._output | |
self.lines = deque() | |
def test(self, scenario): | |
self.parse(scenario) | |
self.app.run() | |
def parse(self, scenario): | |
self.lines.clear() | |
for line in scenario.split('\n'): | |
parsed_line = parse_line(line) | |
if parsed_line: | |
self.lines.append(parsed_line) | |
def _input(self): | |
if len(self.lines) == 0: | |
raise SystemExit | |
current_line = self.lines.popleft() | |
if isinstance(current_line, Input): | |
return str(current_line) | |
else: | |
raise InputError, 'Expected input but got output instead!' + \ | |
' Failed at line "%s".' % current_line | |
def _output(self, result): | |
current_line = self.lines.popleft() | |
if isinstance(current_line, Output): | |
content = current_line.content | |
if content != str(result): | |
raise MatchError, "Output content didn't match!" + \ | |
" Expected %s (%s) but got %s (%s) instead." \ | |
% (content, type(content), result, type(result)) | |
else: | |
raise OutputError, 'Expected output but got input instead!' + \ | |
' Failed at line "%s". Result: %s.' % (current_line, result) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from placidity.scenario_tester import Input, InputError, MatchError, \ | |
Output, OutputError, ScenarioTester | |
from py.test import raises | |
class AbstractApplication: | |
def run(self): | |
try: | |
while True: | |
input = self.input() | |
result = self.interpret(input) | |
if result: | |
self.output(result) | |
except SystemExit: | |
pass | |
class TestScenarioTester: | |
def test_passing_test(self): | |
class Application(AbstractApplication): | |
def interpret(self, input): | |
if input == 'a': | |
return 4 | |
scenario = ''' | |
>>> a = 4 | |
>>> a | |
4 | |
''' | |
scenario_tester = ScenarioTester(Application) | |
scenario_tester.parse(scenario) | |
lines = scenario_tester.lines | |
assert len(lines) == 3 | |
self.assert_line(lines, 1, Input, 'a = 4') | |
self.assert_line(lines, 2, Input, 'a') | |
self.assert_line(lines, 3, Output, '4') | |
# this should not trigger any asserts | |
scenario_tester.test(scenario) | |
def test_input_fail(self): | |
class Application(AbstractApplication): | |
def interpret(self, input): | |
pass | |
scenario = ''' | |
fail | |
''' | |
scenario_tester = ScenarioTester(Application) | |
scenario_tester.parse(scenario) | |
lines = scenario_tester.lines | |
assert len(lines) == 1 | |
self.assert_line(lines, 1, Output, 'fail') | |
raises(InputError, scenario_tester.test, scenario) | |
def test_match_fail(self): | |
class Application(AbstractApplication): | |
def interpret(self, input): | |
if input == 'a': | |
return 42 | |
scenario = ''' | |
>>> a = 4 | |
>>> a | |
5 | |
''' | |
scenario_tester = ScenarioTester(Application) | |
scenario_tester.parse(scenario) | |
lines = scenario_tester.lines | |
assert len(lines) == 3 | |
self.assert_line(lines, 1, Input, 'a = 4') | |
self.assert_line(lines, 2, Input, 'a') | |
self.assert_line(lines, 3, Output, '5') | |
raises(MatchError, scenario_tester.test, scenario) | |
def test_output_fail(self): | |
class Application(AbstractApplication): | |
def interpret(self, input): | |
return 42 | |
scenario = ''' | |
>>> fail | |
>>> fail | |
''' | |
scenario_tester = ScenarioTester(Application) | |
scenario_tester.parse(scenario) | |
lines = scenario_tester.lines | |
assert len(lines) == 2 | |
self.assert_line(lines, 1, Input, 'fail') | |
self.assert_line(lines, 2, Input, 'fail') | |
raises(OutputError, scenario_tester.test, scenario) | |
def assert_line(self, lines, line_number, line_type, line_content): | |
line = lines[line_number - 1] | |
assert isinstance(line, line_type) | |
assert line.content == line_content |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment