gpt4 book ai didi

python - 如何使用脚本将 python 3 单元测试拆分为单独的文件来控制运行哪一个?

转载 作者:行者123 更新时间:2023-12-01 05:03:56 25 4
gpt4 key购买 nike

我想将 Python 3.4 单元测试拆分为单独的模块,并且仍然能够从命令行控制要运行或跳过的测试,就好像所有测试都位于同一个文件中一样。我在这样做时遇到了麻烦。

根据the docs ,命令行参数可用于选择要运行的测试。例如:

TestSeqFunc.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


import random
import unittest

class TestSequenceFunctions(unittest.TestCase):

def setUp(self):
self.seq = list(range(10))

def test_shuffle(self):
# make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))

# should raise an exception for an immutable sequence
self.assertRaises(TypeError, random.shuffle, (1,2,3))

def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)

def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)

if __name__ == '__main__':
unittest.main()

可以通过以下任一方式进行控制:

./TestSeqFunc.py

运行文件中的所有测试,

./TestSeqFunc.py TestSequenceFunctions

运行 TestSequenceFunctions 类中定义的所有测试,最后:

./TestSeqFunc.py TestSequenceFunctions.test_sample

运行特定的test_sample()方法。

我遇到的问题是我找不到允许我执行以下操作的文件组织:

  1. 单独的文件中拥有多个包含多个类和方法的模块
  2. 使用一种包装脚本,它可以对要运行的测试(模块/文件、类、方法)进行同样的控制。

我遇到的问题是我找不到模拟 python3 -m unittest 的方法使用 run_tests.py 的行为脚本。例如,我希望能够做到:

  1. 运行当前目录中的所有测试所以./run_tests.py -v应该做与python3 -m unittest -v相同的事情
  2. 运行一个模块(文件): ./run_tests.py -v TestSeqFunc相当于python3 -m unittest -v TestSeqFunc
  3. 运行一个类: ./run_tests.py -v TestSeqFunc.TestSequenceFunctions相当于python3 -m unittest -v TestSeqFunc.TestSequenceFunctions
  4. 从类中运行特定方法: ./run_tests.py -v TestSeqFunc.TestSequenceFunctions.test_sample相当于python3 -m unittest -v TestSeqFunc.TestSequenceFunctions.test_sample

请注意,我想要:

  1. 能够将参数传递给单元测试,例如之前使用的详细标志;
  2. 允许运行特定的模块、类甚至方法。

到目前为止,我使用 suite()在我的run_all.py中起作用手动加载模块并使用 addTest(unittest.makeSuite(obj)) 将其类添加到套件的脚本。然后,我的 main() 很简单:

if __name__ == '__main__':
unittest.main(defaultTest='suite')

但是使用这个我无法运行特定的测试。最后,我可能只是执行 python3 -m unittest <sys.argv>从里面run_all.py脚本,但这不太优雅......

有什么建议吗?!

谢谢!

最佳答案

这是我的最终 run_all.py:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import unittest
import glob

test_pattern = 'validate_*.py'

if __name__ == '__main__':

# Find all files matching pattern
module_files = sorted(glob.glob(test_pattern))
module_names = [os.path.splitext(os.path.basename(module_file))[0] for module_file in module_files]

# Iterate over the found files
print('Importing:')
for module in module_names:
print(' ', module)
exec('import %s' % module)

print('Done!')
print()

unittest.main(defaultTest=module_names)

注释:

  1. 我使用 exec() 来模拟“导入模块名称”。问题是使用 importlib ( explained here for example ) 将导入模块,但不会为模块内容创建命名空间。当我输入 import os 时,会创建一个“os”命名空间,然后我可以访问 os.path。通过使用 importlib,我无法找到创建该命名空间的方法。 unittest 需要有这样的命名空间;你会得到这些类型的错误:

    Traceback (most recent call last):
    File "./run_all.py", line 89, in <module>
    unittest.main(argv=sys.argv)
    File "~/usr/lib/python3.4/unittest/main.py", line 92, in __init__
    self.parseArgs(argv)
    File "~/usr/lib/python3.4/unittest/main.py", line 139, in parseArgs
    self.createTests()
    File "~/usr/lib/python3.4/unittest/main.py", line 146, in createTests
    self.module)
    File "~/usr/lib/python3.4/unittest/loader.py", line 146, in loadTestsFromNames
    suites = [self.loadTestsFromName(name, module) for name in names]
    File "~/usr/lib/python3.4/unittest/loader.py", line 146, in <listcomp>
    suites = [self.loadTestsFromName(name, module) for name in names]
    File "~/usr/lib/python3.4/unittest/loader.py", line 114, in loadTestsFromName
    parent, obj = obj, getattr(obj, part)
    AttributeError: 'module' object has no attribute 'validate_module1'

    因此使用exec()

  2. 我必须添加 defaultTest=module_names ,否则 main() 默认为当前文件内的所有测试类。由于 run_all.py 中没有测试类,因此不会执行任何操作。因此 defaultTest 必须指向所有模块名称的列表。

关于python - 如何使用脚本将 python 3 单元测试拆分为单独的文件来控制运行哪一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25452546/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com