笨方法学python-14(习题47-49)

习题47:自动化测试

通过测试代码简化测试过程

被测试的代码

class Room(object):
    def __init__(self, name, description):
        self.name = name
        self.description = description
        self.paths = {}
    def go(self, direction):
        return self.paths.get(direction, None)
    def add_paths(self, paths):
        self.paths.update(paths)

测试代码

    from nose.tools import *
from DataMining.BFF27_52 import Room

def test_room():
    gold = Room("GoldRoom",
                """This room has gold in it you can grad.
                There's a door to the north.
                """)      # 测试__init__那个函数,需要输入name和
    assert_equal(gold.name, "GoldRoom")
    assert_equal(gold.paths, {})

def test_room_paths():
    center = Room("Center", "Test room in the center.")
    north = Room("North", "Test room in the nroth.")
    south = Room("South", "Test room in the south.")
    center.add_paths({'north': north, 'south': south})
    assert_equal(center.go('north'), north)    # 走north就到了north
    assert_equal(center.go('south'), south)

def test_map():
    start = Room("Start", "You can go west and down a hole.")
    west = Room("Trees", "There are trees here, you can go east.")
    down = Room("Dungeon", "It's dark down here, you can go up.")

    start.add_paths({'west': west, 'down': down})
    west.add_paths({'east': start})
    down.add_path({'up': start})
    assert_equal(start.go('west'), west)
    assert_equal(start.go('west').go('east'), start)    # 回到原点
    assert_equal(start.go('down').go('up'), start)

有个错,add_paths少写了一个s,加上之后(给的代码里每加)


其实吧,我并没怎么看懂这个测试代码,解释说创建一些小房间,测试基本的房间功能,然后测试了路径,最后测试了整个地图。

尤其assert_equal,书上说它保证了你设置的变量,以及在Room里设置的路径和你的期望相符。

常用于测试代码,用于判断两个值是否相等,不等抛出异常。



习题48:更复杂的用户输入

前面要求用户输入完全正确后才能执行,这里希望用户的输入和常用英语很接近也应该可以。所以建立相关模组实现。

作者在游戏里创建了下面这些语汇:

表示方向: north, south, east, west, down, up, left, right, back.

动词: go, stop, kill, eat.

修饰词: the, in, of, from, at, it

名词: door, bear, princess, cabinet.

数词: 由 0-9 构成的数字.


什么是异常?

异常是运行某个函数时得到的一个错误,函数在碰到错误时会提出一个异常。

处理异常的方法是使用try和except两个关键字


给出测试代码,自己写程序

from nose.tools import *
from DataMining.BFF27_52 import lexicon

def test_direction():
    assert_equal(lexicon.scan("north"), [('direction', 'north')])
    result = lexicon.scan("north south east")
    assert_equal(result, [('direction', 'north'),
                          ('direction', 'south'),
                          ('direction', 'east')])
def test_verbs():
    assert_equal(lexicon.scan("go"), [('verb', 'go')])
    result = lexicon.scan("go kill eat")
    assert_equal(result, [('verb', 'go'),
                          ('verb', 'kill'),
                          ('verb', 'eat')])


def test_stops():
    assert_equal(lexicon.scan("the"), [('stop', 'the')])
    result = lexicon.scan("the in of")
    assert_equal(result, [('stop', 'the'),
                          ('stop', 'in'),
                          ('stop', 'of')])
def test_noun():
    assert_equal(lexicon.scan("bear"), [('noun', 'bear')])
    result = lexicon.scan("bear princess")
    assert_equal(result, [('noun', 'bear'),
                          ('noun', 'princess')])
def test_numbers():
    assert_equal(lexicon.scan("1234"), [('number', 1234)])
    result = lexicon.scan("3 91234")
    assert_equal(result, [('number', 3),
                          ('number', 91234)])
def test_errors():
    assert_equal(lexicon.scan("ASDFAFASDF"), [('error', 'ASDFAFASDF')])
    result = lexicon.scan("bear IAS princess")
    assert_equal(result, [('noun', 'bear'),
                          ('error', 'IAS'),
                          ('noun', 'princess')])

被测试代码(参考 笨方法学python Lesson 46 - 49
class Lexicon(object):
    def scan(self, stuff):
        self.stuff = stuff
        words = stuff.split()    # 对句子进行分割
        sentence = []
        for i in words:
            try:
                sentence.append(('number', int(i)))
            except ValueError:
                if i in ['north', 'south', 'east', 'west', 'down', 'up', 'left', 'right', 'back']:
                    sentence.append(('direction', i))
                elif i in ['go', 'stop', 'kill', 'eat']:
                    sentence.append(('verb', i))
                elif i in ['the', 'in', 'of', 'from', 'at', 'in']:
                    sentence.append(('stop', i))
                elif i in ['door', 'bear', 'princess', 'cabinet']:
                    sentence.append(('noun', i))
                else:
                    sentence.append(('error', i))

        return sentence
lexicon = Lexicon()

虽然理解了,但是根据测试代码写出源代码还是有点困难。



习题49:创建句子

# 在上一习题的基础上
print(lexicon.scan("go north"))
print(lexicon.scan("kill the princess"))
print(lexicon.scan("eat the bear"))
print(lexicon.scan("open the door and smack the bear in the nose"))



匹配(Match)和窥视(Peek)

为了达到这个效果,你需要四样工具:

1. 循环访问元组列表的方法,这挺简单的。

2. 匹配我们的主谓宾设置中不同种类元组的方法。

3. 一个“窥视”潜在元组的方法,以便做决定时用到。

4. 跳过(skip)我们不在乎的内容的方法,例如形容词、冠词等没有用处的词汇。


被测试代码(书上给出的源代码)

class ParserError(Exception):
    pass
class Sentence(object):
    def __init__(self, subject, verb, object):
        self.subject = subject[1]
        self.verb = verb[1]
        self.object = object[1]
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')
    nexta = peek(word_list)
    if nexta == 'noun':
        return match(word_list, 'noun')
    if nexta == 'direction':
        return match(word_list, 'direction')
    else:
        raise ParserError("expected a moun or direction next.")
def parse_subject(word_list, subj):
    verb = parse_verb(word_list)
    obj = parse_object(word_list)
    return Sentence(subj, verb, obj)
def parse_sentence(word_list):
    skip(word_list, 'stop')
    start = peek(word_list)
    if start == 'noun':
        subj = match(word_list, 'noun')
        return parse_subject(word_list, subj)
    elif start == '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)

测试代码

from nose.tools import *
from DataMining import BFF27_49
def test_peek():
    words = [('noun', 'apple'), ('stop', 'the'), ('verb', 'kill')]
    assert_equal(BFF27_49.peek(words), 'noun')
    assert_equal(BFF27_49.peek([]), None)
def test_match():
    assert_equal(BFF27_49.match([], 'noun'), None)
    words = [('noun','apple'),('stop','the'), ('verb','kill')]
    assert_equal(BFF27_49.match(words, 'noun'), ('noun', 'apple'))
    assert_equal(BFF27_49.match(words, 'verb'), None)
# def test_skip():
def test_parse_verb():
    words=[('stop', 'a'), ('stop', 'the'), ('verb', 'kill'), ('noun', 'apple')]
    assert_equal(BFF27_49.parse_verb(words), ('verb', 'kill'))
    words_error=[('stop', 'a'), ('stop', 'the'), ('noun', 'apple'), ('verb', 'kill')]
    assert_raises(BFF27_49.ParserError, BFF27_49.parse_verb, words_error)
def test_parse_object():
    words = [('noun', 'apple'), ('verb', 'kill')]
    assert_equal(BFF27_49.parse_object(words), ('noun', 'apple'))
    words2 = [('direction', 'east'), ('verb', 'kill')]
    assert_equal(BFF27_49.parse_object(words2), ('direction', 'east'))
    words_error = [('stop', 'a'), ('verb', 'run'), ('verb', 'kill')]
    assert_raises(BFF27_49.ParserError, BFF27_49.parse_object, words_error)
def test_parse_sentence():
    words = [('stop', 'a'), ('noun', 'apple'), ('verb', 'kill'), ('direction', 'east')]
    result = BFF27_49.parse_sentence(words)
    assert_equal(result.subject, 'apple')
    assert_equal(result.verb, 'kill')
    assert_equal(result.object, 'east')



猜你喜欢

转载自blog.csdn.net/jesmine_gu/article/details/81002056