20190919-4 单元测试,结对

此作业的要求参见:[https://edu.cnblogs.com/campus/nenu/2019fall/homework/7629]

 

结对伙伴:韩昊

 

 

• 要求1 单元测试。

 此次单元测试利用到的TDD框架为Python集成的unittest,具体为表达式转为逆波兰表达式、后缀表达式求值、中缀表达式求值(分为含括号和不含括号)设计如下单元测试代码:

import unittest
from f4 import *
class UnitTest(unittest.TestCase):
    def test_f4(self):
        pass

    # 表达式转换成逆波兰式功能测试
    def test_middle_to_after(self):
        print("表达式转换成逆波兰式功能单元测试开始:")
        _eq = input("输入一个四则运算中缀表达式:")
        _eq_ans = input("输入此中缀表达式的后缀表达式:")
        self.assertEqual(_eq_ans, Test()._test_middle_to_after(eq=_eq))
        print("表达式转换成逆波兰式功能单元测试结束。", end='\n\n')
        print("表达式求值功能测试完成", end='\n\n')

    # 后缀表达式求值功能测试
    def test_suffix_answer(self):
        print("后缀表达式求值功能测试开始:")
        _eq = input("输入一个后缀表达式:")
        _eq_ans = input("输入一个正确的答案:")
        self.assertEqual(_eq_ans, Test()._test_suffix_answer(eq=_eq))
        print("后缀表达式求值功能测试结束。", end='\n\n')
        print("后缀表达式求值功能测试完成", end='\n\n')

    # 中缀表达式求值功能测试(不含括号)
    def test_answer_nobra(self):
        print("表达式求值功能单元测试(不含括号)开始:")
        _eq = input("输入一个四则运算:")
        _eq_ans = input("输入一个正确的答案:")
        self.assertEqual(_eq_ans ,Test()._test_answer(eq = _eq))
        print("表达式求值功能单元测试结束。", end='\n\n')
        print("表达式求值功能测试完成", end='\n\n')

    # 中缀表达式求值功能测试(含括号)
    def test_answer_bra(self):
        print("表达式求值功能单元测试(含括号)开始:")
        _eq = input("输入一个四则运算:")
        _eq_ans = input("输入一个正确的答案:")
        self.assertEqual(_eq_ans, Test()._test_answer(eq=_eq))
        print("表达式求值功能单元测试结束。", end='\n\n')
        print("表达式求值功能测试完成", end='\n\n')
# 单元测试的入口
if __name__ ==  "__main__":
    unittest.main()

测试1(表达式转逆波兰式):

20190919-4 单元测试,结对_第1张图片

关键功能代码:

# 将中缀表达式转换为后缀表达式
def middle_to_after(s):
    expression = []
    ops = []
    for item in s:
        if item in ['+', '-', '*', '/']:
            while len(ops) >= 0:
                if len(ops) == 0:
                    ops.append(item)
                    break
                op = ops.pop()
                if op == '(' or op_rules[item] > op_rules[op]:
                    ops.append(op)
                    ops.append(item)
                    break
                else:
                    expression.append(op)
        elif item == '(':
            ops.append(item)
        elif item == ')':
            while len(ops) > 0:
                op = ops.pop()
                if op == '(':
                    break
                else:
                    expression.append(op)
        else:
            expression.append(item)

    while len(ops) > 0:
        expression.append(ops.pop())

    return expression

 

测试2(后缀表达式求值):

20190919-4 单元测试,结对_第2张图片

 关键功能代码:

# 计算后缀表达式
def cal_suffix_exp_value(expression):
    stack_value = []
    for item in expression:
        if item in ['+', '-', '*', '/']:
            n2 = stack_value.pop()
            n1 = stack_value.pop()
            result = cal_rules(n1, n2, item)
            stack_value.append(result)
        else:
            stack_value.append(int(item))
    return stack_value[0]

 

测试3(中缀表达式求值):

20190919-4 单元测试,结对_第3张图片

20190919-4 单元测试,结对_第4张图片

关键代码:

def _test_answer(self, eq):
    from fractions import Fraction as f
    _answer = f(eval(eq)).limit_denominator(1000)
    _answer = str(_answer)
    return (_answer)

 

 

• 要求2 详细测试报告

功能1

(1)

起初输入f4,打印出现表达式后,无“?”,按照要求需要换行输出“?”,且在“?”之后输入表达式答案,于是尝试修改代码为:

print(generator + '=\n?')

不过这样使得“?”输出后,紧接着又输出了换行,就像这样:

如何让输出不自动换行呢?经查代码,一个关键改变是:

print(generator + '=\n?', end="")

最终,完美解决

 

(2)

加入一个暴躁的老师或者学生,由于收到的表达式超纲了,愤怒的他没输入答案,直接按下了回车,结果会怎样呢?

20190919-4 单元测试,结对_第5张图片

看到这个我猜他会更愤怒,甚至还会把电脑砸了,我们要防止这样的事发生,那该怎么办呢?切题吧!

while i < num:
    mid_experison = Exp_Generator.Generator()
    generator = mid_experison.generate()
    print(generator + '=\n?', end="")
    suffix_expression = middle_to_after(generator)
    value = cal_suffix_exp_value(suffix_expression)
    answer = input()
    if answer.strip() == '':
        print('仿佛你拒绝回答了这道题,没关系,我们换一道,加油')
        continue
    if '?' in answer:
        answer = answer.replace('?', '')
    print_result(float(answer), value)
    i += 1

最后输出是这样的:

20190919-4 单元测试,结对_第6张图片

 

 

 功能2

(1)

表达式转换成逆波兰式功能测试成功:

20190919-4 单元测试,结对_第7张图片

 TDD(UnitTest)关键代码:

# 表达式转换成逆波兰式功能测试
    def test_middle_to_after(self):
        print("表达式转换成逆波兰式功能单元测试开始:")
        _eq = input("输入一个四则运算中缀表达式:")
        _eq_ans = input("输入此中缀表达式的后缀表达式:")
        self.assertEqual(_eq_ans, Test()._test_middle_to_after(eq=_eq))
        print("表达式转换成逆波兰式功能单元测试结束。", end='\n\n')
        print("表达式求值功能测试完成", end='\n\n')

 

(2)

不含括号表达式计算测试:

20190919-4 单元测试,结对_第8张图片

 TDD(UnitTest)关键代码:

# 表达式求值功能测试(不含括号)
    def test_answer_nobra(self):
        print("表达式求值功能单元测试(不含括号)开始:")
        _eq = input("输入一个四则运算:")
        _eq_ans = input("输入一个正确的答案:")
        self.assertEqual(_eq_ans ,Test()._test_answer(eq = _eq))
        print("表达式求值功能单元测试结束。", end='\n\n')
        print("表达式求值功能测试完成", end='\n\n')

 

(3)

含括号表达式计算测试:

20190919-4 单元测试,结对_第9张图片

  TDD(UnitTest)关键代码:

# 表达式求值功能测试(含括号)
def test_answer_bra(self):
    print("表达式求值功能单元测试(含括号)开始:")
    _eq = input("输入一个四则运算:")
    _eq_ans = input("输入一个正确的答案:")
    self.assertEqual(_eq_ans, Test()._test_answer(eq=_eq))
    print("表达式求值功能单元测试结束。", end='\n\n')
    print("表达式求值功能测试完成", end='\n\n')

 

 

 功能3

(1)

20190919-4 单元测试,结对_第10张图片

运行出错,是因为程序要根据用户输入的数字,来决定要输出的表达式的行数,而python默认从终端读进来的参数是str类型,所以需要将str类型的参数转换为int类型才可以利用到循环控制中。

# 功能三输出一行计算表达式及结果
def print_exp_result(num):
    i = 0
    num = int(num)
    while i < num:
        generate = Exp_Generator.Generator()
        mid_experision = generate.generate()
        suffix_expression = middle_to_after(mid_experision)
        value = cal_suffix_exp_value(suffix_expression)
        mid_experision += '='
        print('%-15s %-15s' % (mid_experision, value))
        i += 1

修改成功后:

20190919-4 单元测试,结对_第11张图片

 

 

 收获

接触python时间不长,第一次用python写如此规模的程序,感受到了python语法如此简洁且资源库如此强大带来的方便。不过在本次编程由fail到pass过程中,之所以fail的原因,大部分还是对语言本身理解掌握不够、需求分析不彻底不充分,最大的收获是,问题驱动下的学习方式,比单纯为了学技术而学技术,更实际可靠。

 

 

• 要求4 版本控制。

代码地址:[https://e.coding.net/secret/ASETest1_3.git]

你可能感兴趣的:(20190919-4 单元测试,结对)