LPTHW ex49在单元测试

时间:2016-02-16 04:26:15

标签: python-3.x nose

我在“学习Python艰难之路”一书中做了ex49的练习。 我在nosetest中得到了AttributeError,而我可以通过python shell中的excute命令传递。 我在Ubuntu 15.10编码,python版本是3.4.3。 目录结构如下:

.:
bin  docs  ex49  lexicon.py  parser.py  readme  setup.py  tests

./bin:

./docs:

./ex49:
__init__.py

./tests:
ex49_test.py  __init__.py

lexicon.py:

#!/usr/bin/env python
# encoding: utf-8
direction_base = ['north', 'south', 'west', 'east', 'down', 'up', 'left', 'right', 'back']
verb_base = ['go', 'kill', 'eat', 'open']
stop_base = ['the', 'in', 'of', 'it']
noun_base = ['door', 'bear', 'princess', 'carbinet']


def convert_number(s):
    try:
        return int(s)
    except ValueError:
        return None

def scan(strInput):
    wordList = strInput.lower().split(' ')
    resultSentence = []

    for word in wordList:
        if word in direction_base:
            resultSentence.append(('direction', word))
        elif word in verb_base:
            resultSentence.append(('verb', word))
        elif word in stop_base:
            resultSentence.append(('stop', word))
        elif word in noun_base:
            resultSentence.append(('noun', word))
        elif convert_number(word) is not None:
            resultSentence.append(('number', int(word)))
        else:
            resultSentence.append(('error', word))

    return resultSentence

parser.py:

#!/usr/bin/env python
# encoding: utf-8

class ParserError(Exception):
    pass

class Sentence(object):
    def __init__(self, subject, verb, number, object):
        # remember we take ('noun','princess') tuples and convert them
        self.subject = subject[1]
        self.verb = verb[1]
        self.number = number[1]
        self.object = object[1]

    def to_tuple(self):
        return (self.subject, self.verb, self.number, self.object)

def peek(word_list):
    if word_list:
        word = word_list[0]
        return word[0]
    else:
        return None


def match(word_list, expecting):
    if word_list:
        word = word_list.pop(0)

        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:
        raise ParserError("Expected a verb next.")


def parse_object(word_list):
    skip(word_list, 'stop')
    next_item = peek(word_list)

    if next_item == 'noun':
        return match(word_list, 'noun')
    elif next_item == 'direction':
        return match(word_list, 'direction')
    else:
        raise ParserError("Expected a noun or direction next.")

def parse_number(word_list, number):
   skip(word_list, 'stop')

   if peek(word_list) == 'number':
       return match(word_list, 'number')
   else:
       return ('number', 1)

def parse_subject(word_list, subj):
    verb = parse_verb(word_list)
    number = parse_number(word_list)
    obj = parse_object(word_list)

    return Sentence(subj, verb, number, obj)


def parse_sentence(word_list):
    skip(word_list, 'stop')
    start_item = peek(word_list)

    if start_item == 'noun':
        subj = match(word_list, 'noun')
        return parse_subject(word_list, subj)
    elif start_item == 'verb':
        # assume the subject is the player then
        return parse_subject(word_list, ('noun', 'player'))
    else:
        raise ParserError("Must start with subject, object, or verb not: %s" % start_item)

ex49_test.py:

#!/usr/bin/env python
# encoding: utf-8
from nose.tools import *
import lexicon
import parser

def test_sentence_obj():
    s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
    assert_equal(s.subject, 'bear')
    assert_equal(s.verb, 'eat')
    assert_equal(s.number, 1)
    assert_equal(s.object, 'door')
    assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))

def test_peek():
    word_list = lexicon.scan('princess')
    assert_equal(parser.peek(word_list), 'noun')
    assert_equal(parser.peek(None), None)

def test_match():
    word_list = lexicon.scan('princess')
    assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
    assert_equal(parser.match(word_list, 'stop'), None)
    assert_equal(parser.match(None, 'noun'), None)

def test_skip():
    word_list = lexicon.scan('bear eat door')
    assert_equal(word_list, [('noun', 'bear'), ('verb', 'eat'), ('noun', 'door')])
    parser.skip(word_list, 'noun')
    assert_equal(word_list, [('verb', 'eat'), ('noun', 'door')])

def test_parse_verb():
    word_list = lexicon.scan('it eat door')
    assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
    word_list = lexicon.scan('bear eat door')
    assert_raise(parser.ParserError, parser.parse_verb, word_list)

def test_parse_object():
    word_list = lexicon.scan('the door')
    assert_equal(parser.parse_object(word_list), ('noun', 'door'))
    word_list = lexicon.scan('the east')
    assert_equal(parser.parse_object(word_list), ('direction', 'east'))
    word_list = lexicon.scan('the it')
    assert_raise(parser.ParserError, parser.parse_object, word_list)

def test_parse_subject():
    word_list = lexicon.scan('eat door')
    subj = ('noun', 'bear')
    s = parser.parse_subject(word_list, subj)
    assert_raise(s.to_tuple(), ('bear', 'eat', 1, 'door'))

def test_parse_sentence():
    word_list = lexicon.scan('the bear eat door')
    s = parser.parse_sentence(word_list)
    assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))
    word_list = lexicon.scan('in the door')
    s = parser.parse_sentence(word_list)
    assert_equal(s.to_tuple(), ('player', 'eat', 1, 'door'))
    word_list = lexicon.scan('north eat door')
    assert_equal(parser.ParserError, parser.parse_sentence, word_list)

def test_unknown_words():
    word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
    s = parser.parse_sentence(word_list)
    assert_equal(s.to_tuple(), ('bear', 'eat', 1, 'door'))

def test_number():
    word_list = lexicon.scan('xxx the xxx bear xxx eat xxx 5 xxx door xxx')
    s = parser.parse_sentence(word_list)
    assert_equal(s.to_tuple(), ('bear', 'eat', 5, 'door'))

执行错误:

~/Documents/python3/practice/ex49$ nosetests3 tests/
EEEEEEEEEE
======================================================================
ERROR: tests.ex49_test.test_sentence_obj
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 8, in test_sentence_obj
    s = parser.Sentence(('noun', 'bear'), ('verb', 'eat'), ('number', 1), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'Sentence'

======================================================================
ERROR: tests.ex49_test.test_peek
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 17, in test_peek
    assert_equal(parser.peek(word_list), 'noun')
AttributeError: 'module' object has no attribute 'peek'

======================================================================
ERROR: tests.ex49_test.test_match
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 22, in test_match
    assert_equal(parser.match(word_list, 'noun'), ('noun', 'princess'))
AttributeError: 'module' object has no attribute 'match'

======================================================================
ERROR: tests.ex49_test.test_skip
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 29, in test_skip
    parser.skip(word_list, 'noun')
AttributeError: 'module' object has no attribute 'skip'

======================================================================
ERROR: tests.ex49_test.test_parse_verb
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 34, in test_parse_verb
    assert_equal(parser.parse_verb(word_list), ('verb', 'eat'))
AttributeError: 'module' object has no attribute 'parse_verb'

======================================================================
ERROR: tests.ex49_test.test_parse_object
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 40, in test_parse_object
    assert_equal(parser.parse_object(word_list), ('noun', 'door'))
AttributeError: 'module' object has no attribute 'parse_object'

======================================================================
ERROR: tests.ex49_test.test_parse_subject
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 49, in test_parse_subject
    s = parser.parse_subject(word_list, subj)
AttributeError: 'module' object has no attribute 'parse_subject'

======================================================================
ERROR: tests.ex49_test.test_parse_sentence
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 54, in test_parse_sentence
    s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'

======================================================================
ERROR: tests.ex49_test.test_unknown_words
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 64, in test_unknown_words
    s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'

======================================================================
ERROR: tests.ex49_test.test_number
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/nose/case.py", line 198, in runTest
    self.test(*self.arg)
  File "/home/chungyi/Documents/python3/practice/ex49/tests/ex49_test.py", line 69, in test_number
    s = parser.parse_sentence(word_list)
AttributeError: 'module' object has no attribute 'parse_sentence'

----------------------------------------------------------------------
Ran 10 tests in 0.007s

FAILED (errors=10)

1 个答案:

答案 0 :(得分:0)

您的问题出在parser模块命名中。不幸的是,python中有一个内置的parser模块:尝试在任何文件夹中运行python并运行import parser。现在检查parser.__file__以查看它引用的实际模块:对我来说它指的是:

>>> import parser
>>> parser.__file__
'/usr/lib/python2.7/lib-dynload/parser.x86_64-linux-gnu.so'

所以你的ex49_test.py选错了parser这就是python试图告诉你的:AttributeError: 'module' object has no attribute 'match'意味着在这个模块中没有match方法。将解析器重命名为其他内容,看看生活是否变得更好。