此作业的要求参见:[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(表达式转逆波兰式):
关键功能代码:
# 将中缀表达式转换为后缀表达式 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(后缀表达式求值):
关键功能代码:
# 计算后缀表达式 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(中缀表达式求值):
关键代码:
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)
加入一个暴躁的老师或者学生,由于收到的表达式超纲了,愤怒的他没输入答案,直接按下了回车,结果会怎样呢?
看到这个我猜他会更愤怒,甚至还会把电脑砸了,我们要防止这样的事发生,那该怎么办呢?切题吧!
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
最后输出是这样的:
功能2
(1)
表达式转换成逆波兰式功能测试成功:
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)
不含括号表达式计算测试:
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)
含括号表达式计算测试:
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)
运行出错,是因为程序要根据用户输入的数字,来决定要输出的表达式的行数,而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
修改成功后:
收获
接触python时间不长,第一次用python写如此规模的程序,感受到了python语法如此简洁且资源库如此强大带来的方便。不过在本次编程由fail到pass过程中,之所以fail的原因,大部分还是对语言本身理解掌握不够、需求分析不彻底不充分,最大的收获是,问题驱动下的学习方式,比单纯为了学技术而学技术,更实际可靠。
• 要求4 版本控制。
代码地址:[https://e.coding.net/secret/ASETest1_3.git]