仍然使用ex46的项目骨架进行测试,NAME文件夹命名为ex49,其中放置需要测试的模块parser.py,也可以使用ex48中的NAME文件,将两次或多次测试一并进行。tests文件夹中放置parser_test.py.
from NAME import module #NAME文件夹名,module模块名
**parse_tests.py**
from nose.tools import *
from ex49 import parse
def test_parse_sentence_normal1():
# start with subject or object
word_list = [('noun', 'bear'), ('verb', 'kill'), ('direction', 'east')]
result = parse.parse_sentence(word_list)
assert_equal((result.subject, result.verb, result.object), ('bear', 'kill', 'east'))
def test_parse_sentence_normal2():
# start with verb
word_list = [('verb', 'kill'), ('direction', 'east')]
result = parse.parse_sentence(word_list)
assert_equal((result.subject, result.verb, result.object), ('player', 'kill', 'east'))
def test_raises_type_error():
"""
If you want to test many assertions about exceptions
in a single test, you may want to use assert_raises instead
"""
# middle with stop
word_list = [('noun', 'bear'), ('stop', 'the'), ('direction', 'east')]
assert_raises(parse.ParseError, parse.parse_sentence, word_list)
def test_raises_type_error1():
# start with stop
word_list = [('stop', 'the'), ('noun', 'bear'), ('direction', 'east')]
assert_raises(parse.ParseError, parse.parse_sentence, word_list)
def test_raises_type_error2():
# end with stop
word_list = [('noun', 'bear'), ('verb', 'kill'), ('stop', 'the')]
assert_raises(parse.ParseError, parse.parse_sentence, word_list)
assert_raises = assertRaises(expected_exception, *args, **kwargs) method of nose.tools.trivial.Dummy instance
Fail unless an exception of class expected_exception is raised
by the callable when invoked with specified positional and
keyword arguments. If a different type of exception is
raised, it will not be caught, and the test case will be
deemed to have suffered an error, exactly as for an
unexpected exception.
If called with the callable and arguments omitted, will return a
context object used like this::
with self.assertRaises(SomeException):
do_something()
An optional keyword argument 'msg' can be provided when assertRaises
is used as a context object.
The context manager keeps a reference to the exception as
the 'exception' attribute. This allows you to inspect the
exception after the assertion::
with self.assertRaises(SomeException) as cm:
do_something()
the_exception = cm.exception
self.assertEqual(the_exception.error_code, 3)
**parse.py**
class ParseError(Exception):
pass
class Sentence():
def __init__(self, subject, verb, object):
# remember we take('noun','princess')tuples and convert them
self.subject = subject[1]
self.verb = verb[1]
self.object = object[1]
def peek(word_list):
# 若实参有输入,则将列表中第一组元素赋值给word,并返回word元组中第一个元素
# 若无输入,返回None
if word_list:
word = word_list[0]
return word[0]
else:
return None
def match(word_list, expecting):
# 若实参有输入,则将列表中第一组元素赋值给word,并返回word元组中第一个元素
# 继续判断,若word第一个元素和期望值相等,返回word,若不相等,返回None
# 若无输入,返回None
if word_list:
word = word_list.pop(0)
print(word)
if word[0] == expecting:
return word
else:
return None
else:
return None
def skip(word_list, word_type):
while peek(word_list) == word_type:
match(word_list, word_type)
def parse_verb(word_list):
skip(word_list, 'stop')
if peek(word_list) == 'verb':
return match(word_list, 'verb')
else:
# 当程序出现错误,python会自动引发异常,也可以通过raise显示地引发异常。
# 一旦执行了raise语句,raise后面的语句将不能执行。
raise ParseError("Expected a verb next.")
def parse_object(word_list):
skip(word_list, 'stop')
next = peek(word_list)
if next == 'noun':
return match(word_list, 'noun')
if next == 'direction':
return match(word_list, 'direction')
else:
raise ParseError("Excepted a noun or direction next.")
def parse_subject(word_list, subj):
"""处理文法部分"""
# 若当前是verb类型,就满足期望值,pop掉当前,继续后面判断
verb = parse_verb(word_list)
# 若当前是noun或direction类型,就满足期望,pop掉当前,继续后面判断
obj = parse_object(word_list)
# 返回Sentence类
return Sentence(subj, verb, obj)
def parse_sentence(word_list):
# 若(type,word)组第一个组的type是stop,则使用pop将word_list第一个组删除,start赋值为第二个组的type值
# 若不是,则将第一个组的type赋值给start
skip(word_list, 'stop')
start = peek(word_list)
# 继续判断,若start为'noun',进行match匹配,若匹配成功,将word_list第一个组赋值给subj,并pop删除掉,等待下一次调用判断
if start == 'noun':
subj = match(word_list, 'noun')
# 对当前元组进行文法部分处理
return parse_subject(word_list, subj)
elif start == 'verb':
return parse_subject(word_list, ('noun', 'player'))
else:
raise ParseError("Must start with subject, object, or verb not: %s" % start)