美文网首页
python unittest只跑失败的用例

python unittest只跑失败的用例

作者: 假程序员 | 来源:发表于2019-11-26 00:38 被阅读0次

提供一个用于记录unittest运行失败的case的模块,当一个测试方法failure之后,会在项目根目录下创建一个failure_rerun.sh或failure_rerun.bat文件来存储测试失败的case的访问方式。这样就可以以shell脚本或dos批处理的方式直接运行失败的case。该模块中的装饰器同时支持ddt和paramunittest。
请注意:该段代码没有经过windows测试,所以可能出现路径分隔符的问题,请使用windows用户自行调试修改。

# coding=utf-8
import sys
import functools
import importlib
from manage import root_path  # 项目根目录,需自行实现


def __deal_fail_command(file_name, s="", flag=True):  # flag=true,add failure.flag=false,delete success
    unit_command = "python -m unittest"
    if sys.platform == "win32":
        file_name = root_path + "\\" + file_name + ".bat"
    else:
        file_name = root_path + "/" + file_name + ".sh"
    with open(file_name, "a+"):
        pass
    global line
    line = None
    with open(file_name, "r") as f:
        line = f.readline()
    if flag:
        if line.startswith(unit_command):
            if line.find(s) == -1:
                line += " " + s
        else:
            line = unit_command + " " + s
    else:
        if line.startswith(unit_command):
            if line.find(s) != -1:
                line = "".join(line.split(" " + s))
        else:
            line = unit_command
    with open(file_name, "w") as f:
        f.write(line)


def rerun_class(cls, prefix="test"):
    for name, func in list(cls.__dict__.items()):
        if hasattr(func, "__call__") and name.startswith(prefix):
            setattr(cls, name, rerun_method(func))

    return cls


def rerun_method(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        s = None
        if s is None:
            test_instance = args[0]
            native_c = type(test_instance)
            # 若虚拟类的模块是"paramunittest",则表示该类是由paramunittest构造的
            if native_c.__module__ == "paramunittest":
                father = native_c.__bases__  # 获取本类的super集
                for T in father:
                    real_m, real_c = T.__module__, T
                    if native_c.__name__.startswith(real_c.__name__ + "_") != -1:
                        s = native_c.__name__ + "." + getattr(test_instance, "_testMethodName")
                        module_path = importlib.import_module(real_m).__file__  # type:str
                        module_name = module_path.split("/")[-1].split(".")[0]
                        module_dir = "/".join(module_path.split("/")[0:-1])
                        if module_dir.startswith(root_path):
                            path = module_dir[root_path.__len__() + 1:]
                            s = ".".join(path.split("/")) + "." + module_name + "." + s
                        break
            else:
                s = native_c.__name__ + "." + getattr(test_instance, "_testMethodName")
                module_path = importlib.import_module(native_c.__module__).__file__  # type:str
                module_name = module_path.split("/")[-1].split(".")[0]
                module_dir = "/".join(module_path.split("/")[0:-1])
                if module_dir.startswith(root_path):
                    path = module_dir[root_path.__len__() + 1:]
                    s = ".".join(path.split("/")) + "." + module_name + "." + s
        try:
            func(*args, **kwargs)
            __deal_fail_command("failure_rerun", s, flag=False)
            return
        except AssertionError:
            __deal_fail_command("failure_rerun", s)
            raise

    return wrapper

能够通过命令行重新执行仍旧不完美,故此提供一个直接py脚本。其中的参数is_test_all可以控制是否执行全部case,当is_test_all==False时,该脚本会自动解析先前所生成的failure_rerun.*文件,并以其中的失败case构建一个testSuite,并重新运行这些case。

# coding=utf-8
import os
import unittest
import common.HTMLTestRunner as HTMLTestRunner  # 这是网上的HTMLTestRunner
import unittest.loader as loader
import unittest.suite as suite

root_path = os.path.abspath(os.path.dirname(__file__))

is_test_all = False  # 用于控制运行all case和failure case

if __name__ == '__main__':
    with open("failure_rerun.sh", "r") as f:  # set is_test_all
        line = f.readline()
        if is_test_all:
            pass
        elif line == "python -m unittest" or line == "":
            is_test_all = True

    if is_test_all:  # run all case
        discover = unittest.defaultTestLoader.discover("testcases", pattern="*.py", top_level_dir=None)
        fp = open('reports/my_report.html', 'wb')
        runner = HTMLTestRunner.HTMLTestRunner(
            verbosity=2,
            stream=fp,
            title=u'跑all case',
            description='This demonstrates the report output by HTMLTestRunner.'
        )
        runner.run(discover)
        fp.close()
    else:  # run failure case
        line = line["python -m unittest".__len__():]
        test_list = line.split(" ")

        test_suite = suite.TestSuite()
        for test in test_list:
            if test.__len__() > 0 and test.__contains__("."):
                test_suite.addTest(loader.TestLoader().loadTestsFromName(name=test))
        fp = open('reports/my_report.html', 'wb')
        runner = HTMLTestRunner.HTMLTestRunner(
            verbosity=2,
            stream=fp,
            title=u'只跑失败的case',
            description='This demonstrates the report output by HTMLTestRunner.'
        )
        runner.run(test_suite)
        fp.close()

一个结构示例 image.png

为了便于效果演示,在此提供了一个用于测试的的脚本。

import unittest
from decorator.rerun import rerun_class, rerun_method


@rerun_class
class T(unittest.TestCase):

    def setUp(self):
        print "setUp"

    def tearDown(self):
        print "tearDown"

    def test_001(self):
        print "test_001"

    @rerun_method
    def test_002(self):
        print "test_002"
        assert False

    def test_003(self):
        print "test_003"
        assert False

相关文章

网友评论

      本文标题:python unittest只跑失败的用例

      本文链接:https://www.haomeiwen.com/subject/lovswctx.html