【问题标题】:Are my Unit tests written correctly to test my code functions我的单元测试是否正确编写以测试我的代码功能
【发布时间】:2019-12-03 01:05:50
【问题描述】:

尝试编写单元测试来测试我的 Python 代码项目。

我有一个 gestioner.py 文件,它检查用户输入并查看它们是否有效(来自允许的列表)(来自“danger_list”) 然后还检查输入的命令是否输入了任何可疑字符以防止安全攻击。

现在我想在 Gestioner.py 中的函数代码中添加单元测试

正在关注 Stackoverflow 问题中的文章:Writing unit tests in Python: How do I start?

然后是 py.test 文档 (https://docs.pytest.org/en/latest/contents.html)

我已经编写了以下 test_gestioner.py 来开始我的单元测试,如下所示:

而且我所有的三个测试似乎一直在通过。但是我怀疑我的这些测试是否真的正确地测试了我的代码,因为当我期望测试失败时,测试仍然通过。

我是否正确地对我的代码进行单元测试? 在我看来我不是,所以请建议我在单元测试中哪里出错了?

这是我的主要脚本,Gestioner.py



import sys
import re


class CmdGestioner:
    _allowed_list = ['fichier', 'binfile', 'prep', 'rep' ]
    _danger_list = ['gen', 'regen'] 

    def __init__(self):
        None

    def chk_cmds(self, mycmd):
        print('chk_cmds: lets look term at {}'.format(mycmd))
        regex = re.compile(r'[&`%;$><!#]')
        msg = bool(regex.search(mycmd))
        print('My command: ' +mycmd)
        if msg is True:
            print(msg)
            print('Found a suspicious entry in the command : {}'.format(mycmd))
            return -1
        else:
            print('Command seems clean {}'.format(mycmd))
            return 0


    def is_valid(self, in_command):
        valid = True


        cmd_mtg_str = ''.join(str(elem) for elem in in_command)



        for term in cmd_mtg_str.split():

            if term.strip('--') not in self._allowed_list:
                if term.strip('--') in self._forbidden_list:
                    valid = False
                    print('Found a forbidden Sec_Service command '+term)
                else:
                    print ('%s not found in list so need to runs checks on this!' % (term))
                    checkResult = self.chk_cmds(term)
                    if checkResult == -1:
                        valid = False
            else:
                print ('Found in list so term %s is valid' % (term))
        return valid




test_command = ' '.join(str(elem) for elem in sys.argv[1:])
cmd = CmdGestioner()

status = cmd.is_valid(test_command)
print ('\nStatus for command: %s is %s' % (test_command,status))

和我的单元测试文件 (test_gestioner.py)

import sys
import re
import unittest
import pytest
from gestioner import CmdGestioner

cmd = CmdGestioner()


def test_chk_cmds_valid():
    mycmd = "--binfile testbinfile"
    cmd.chk_cmds(mycmd)
    assert 'Status for command: ' +mycmd +' is True'


def test_chk_cmds_danger():
    mycmd = "--gen genf"
    cmd.chk_cmds(mycmd)
    assert 'Status for command: ' +mycmd +' is False'


def test_chk_cmds_attacks():
    mycmd = ";ls"
    cmd.chk_cmds(mycmd)
    assert 'Found a suspicious entry in the command : ' .format(mycmd)
    assert 'Status for command: ' +mycmd +' is False


我的单元测试正在执行:

PS C:\Work\Questions_forums\SecService_messaging> py.test -v                                                                                                                                                                                       ================================================================================== test session starts =============================================================================================================================
platform win32 -- Python 3.7.4, pytest-5.0.1, py-1.8.0, pluggy-0.12.0 -- c:\users\SecUser\appdata\local\programs\python\python37\python.exe
cachedir: .pytest_cache
metadata: {'Python': '3.7.4', 'Platform': 'Windows-10-10.0.18362-SP0', 'Packages': {'pytest': '5.0.1', 'py': '1.8.0', 'pluggy': '0.12.0'}, 'Plugins': {'html': '1.21.1', 'metadata': '1.8.0'}}
rootdir: C:\Work\Questions_forums\SecService_messaging
plugins: html-1.21.1, metadata-1.8.0
collected 3 items

test_gestioner.py::test_chk_cmds_valid PASSED                                                                                                                                                                                                                           [ 33%]
test_gestioner.py::test_chk_cmds_danger PASSED                                                                                                                                                                                                                          [ 66%]
test_gestioner.py::test_chk_cmds_attacks PASSED                                                                                                                                                                                                                         [100%]

========================================================================================================================== 3 passed in 0.03 seconds ==========================================================================================================================

【问题讨论】:

  • 你似乎没有断言来自cmd.chk_cmds(mycmd)的返回值。

标签: python unit-testing pytest


【解决方案1】:

不,您的单元测试编写不正确。 chk_cmd 方法不返回字符串,它打印到标准输出,但是您的断言语句正在寻找您的 chk_cmd 的结果以等于打印的结果。相反,assert 语句正在检查字符串是否等于 true,其中一个或多个章程的任何字符串都被认为是 true,因此这些测试应该始终通过。要使 assert 语句在编写时正常工作,您需要从 chk_cmd 方法返回预期的字符串或测试其他内容。例如

assert cmd.is_valid('rep')
assert cmd.chk_cmds(mycmd) == -1
assert cmd.chk_cmd(mycmd) == 0

看起来您可能来自具有 -1 和 0 返回值的 C 编程背景。如果您将这些值重写为 True 和 False,它将改进您的代码和断言。以下重构:

class CmdGestioner:
    _allowed_list = ['fichier', 'binfile', 'prep', 'rep' ]
    _danger_list = ['gen', 'regen']

    def chk_cmds(self, mycmd):
        regex = re.compile(r'[&`%;$><!#]')
        msg = bool(regex.search(mycmd))
        if msg is True:
            return False
        else:
            return True


    def is_valid(self, in_command):
        valid = True
        cmd_mtg_str = ''.join(str(elem) for elem in in_command)
        for term in cmd_mtg_str.split():
            if term.strip('--') not in self._allowed_list:
                if term.strip('--') in self._danger_list:
                    valid = False
                else:
                    if self.chk_cmds(term):
                        valid = False
        return valid

更易读(省略打印语句以便更清楚地看到提议的更改),并且它允许将断言重写为

assert cmd.chk_cmds(mycmd)

因为该方法现在返回 true 或 false,所以您不必在断言中添加条件语句。

您当前断言的方式应该始终评估为真,因为您正在检查字符串而不是标准输出。

【讨论】:

  • 谢谢 infosmith,很好很简单。
猜你喜欢
  • 2015-03-15
  • 1970-01-01
  • 2014-02-24
  • 1970-01-01
  • 2013-02-24
  • 2023-03-16
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
相关资源
最近更新 更多