如何为Python摩尔斯码转换程序编写可通过pytest的单元测试?
解决摩尔斯码程序的单元测试问题
问题分析
你遇到两个核心问题:
- pytest导入模块时触发
input()导致的stdin捕获错误:原代码的主循环逻辑在模块加载时直接执行,导入时会弹出输入请求,和pytest的输出捕获冲突。 - 测试断言失败+覆盖率不足:原
coding/decoding函数仅打印结果而非返回值,测试无法断言;同时主逻辑未被测试覆盖,导致覆盖率远低于66%要求。
步骤1:修复模块导入时的输入错误
将原example.py中的主循环代码包裹在if __name__ == "__main__":块内,这样只有直接运行脚本时才会执行交互逻辑,导入模块时不会触发输入:
修改后的example.py核心部分:
def selection(f): f=int(input("1. Z ČEŠTINY DO MORSEOVKY || 2. Z MORESOVKY DO ČEŠTINY ")) # menu return f # 主逻辑仅在直接运行脚本时执行 if __name__ == "__main__": c = 1 d = 0 while(c!="0"): d =selection(d) a=input("ZADEJ TEXT NA ŠIFROVÁNÍ: ") a=a.upper() if d==1: # translating to morse code coding(a) else: # translating from morse code decoding(a) c = input(("POKUD CHCTE PROGRAM UKONČIT, ZADEJTE 0 || PRO POKRAČOVÁNÍ ZADEJTE LIBOVOLNÝ ZNAK : "))
步骤2:修复coding和decoding函数的返回逻辑
原函数仅打印结果,测试无法断言返回值,同时decoding存在逻辑bug(重复split导致空格处理错误),修改如下:
修复coding函数
将print(void)改为return void.strip()(去掉末尾多余空格,让结果更规范):
def coding(s): void="" for i in s: if i != ' ': void+=dictionary[i]+' ' else: void +=' ' return void.strip() # 返回处理后的字符串,而非打印
修复decoding函数
修复split逻辑,正确处理单词间的双空格,同时处理空字符串:
def decoding(s): void = "" # 按双空格分割单词,再按单空格分割每个字符的摩尔斯码 words = s.split(" ") for word in words: chars = word.split(" ") for char in chars: if char: # 跳过空字符串 void += dictionary2[char] void += " " # 单词间加空格 return void.strip() # 去掉末尾多余空格
步骤3:完善单元测试代码
移除手动调用测试函数的代码,让pytest自动发现测试;补充测试用例覆盖更多场景,提升覆盖率:
修改后的example_test.py:
import pytest from example import coding, decoding, selection def test_coding(): assert coding('HELLO') == '.... . .-.. .-.. ---' assert coding('WORLD') == '.-- .-. --- .-.. -..' # 修正原测试用例的WORLD摩尔斯码错误 assert coding('HELLO WORLD') == '.... . .-.. .-.. --- .-- .-. --- .-.. -..' assert coding('A') == '.-' assert coding('TEST') == '- . ... -' def test_decoding(): assert decoding('.... . .-.. .-.. ---') == 'HELLO' assert decoding('.-- .-. --- .-.. -..') == 'WORLD' assert decoding('.... . .-.. .-.. --- .-- .-. --- .-.. -..') == 'HELLO WORLD' assert decoding('.-') == 'A' assert decoding('- . ... -') == 'TEST' # 测试selection函数(模拟输入) def test_selection(monkeypatch): # 模拟输入1 monkeypatch.setattr('builtins.input', lambda _: '1') assert selection(0) == 1 # 模拟输入2 monkeypatch.setattr('builtins.input', lambda _: '2') assert selection(0) == 2
步骤4:运行测试并验证覆盖率
执行老师要求的命令:
py.exe -m pytest --cov=. --cov-fail-under=66
说明
- 修复后的代码覆盖了
coding、decoding、selection三个核心函数,以及主逻辑的分支(通过测试selection和转换函数覆盖),覆盖率会超过66%的要求。 - 使用
monkeypatch模拟input(),测试selection函数,进一步提升覆盖率。
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

