有没有办法从外部传递/注入测试参数



假设我在 tests.py 中有以下测试类:

class MyTest(unittest.TestCase):
@classmethod
def setUpClass(cls, ip="11.111.111.111",
browserType="Chrome",
port="4444",
h5_client_url="https://somelink.com/",
h5_username="username",
h5_password="pass"):
cls.driver = get_remote_webdriver(ip, port, browserType)
cls.driver.implicitly_wait(30)
cls.h5_client_url = h5_client_url
cls.h5_username = h5_username
cls.h5_password = h5_password
@classmethod
def tearDownClass(cls):
cls.driver.quit()
def test_01(self):
# test code
def test_02(self):
# test code
...
def test_N(self):
# test code

我所有的测试(test_01到test_N)都使用setUpClass中提供的参数。这些参数具有默认值:

ip="11.111.111.111",
browserType="Chrome",
port="4444",
h5_client_url="https://somelink.com/",
h5_username="username",
h5_password="pass"

所以我想知道我是否可以为这些参数注入新值。我想从另一个 python 脚本中执行此操作,因此不会对测试代码进行任何更改或只有微小更改。

注意:我想通过批处理/shell 命令运行我的测试并将测试的输出保存到日志文件(将标准输出重定向到该日志文件)

我所做的一个想法是创建一个函数装饰器,它传递带有key=parameter_namevalue=parameter_new_value的字典,但我不得不在 tests.py 中编写许多其他代码:

  1. 我定义了function_decorator逻辑

  2. 我将该@function_decorator注释放在我想要装饰的每个功能之上

  3. 函数装饰器需要该字典作为参数,因此我制作了一个main,看起来像这样:

    if __name__ == '__main__':
    # terminal command to run tests should look like this /it is executed by the run-test PARROT command/
    #     python [this_module_name] [dictionary_containing_parameters] [log_file.log] *[tests]
    parser = argparse.ArgumentParser()
    # add testbeds_folder as scripts' first parameter, test_log_file as second and tests as the rest
    parser.add_argument('dictionary_containing_parameters')
    parser.add_argument('test_log_file')
    parser.add_argument('unittest_args', nargs='*')
    args = parser.parse_args()
    dictionary_containing_parameters = sys.argv[1]
    test_log_file = sys.argv[2]
    # removes the "dictionary_containing_parameters" and "test_log_file" from sys.args - otherwise an error occurs unittest TestRunner
    sys.argv[1:] = args.unittest_args
    # executes the test/tests and save the output to the test_log_file
    with open(test_log_file, "w") as f:
    runner = unittest.TextTestRunner(f)
    unittest.main(defaultTest=sys.argv[1:], exit=False, testRunner=runner)
    

这是一个可能的解决方案:

您可以通过以下方式从其他模块运行测试:

if __name__ == '__main__':
testbed_dict = {"ip": "11.111.111.112",
"browserType": "Chrome",
"port": "4444",
"h5_client_url": "https://new_somelink.com/",
"h5_username": "new_username",
"h5_password": "new_pass"}
sys.argv.append(testbed_dict)
from your_tests_module import *
with open("test.log", "w") as f:
runner = unittest.TextTestRunner(f)
unittest.main(argv=[sys.argv[0]], defaultTest='test_class.test_name', exit=False, testRunner=runner)

你可以注意到argv=[sys.argv[0]]unittest.main(argv=[sys.argv[0]], defaultTest='test_class.test_name', exit=False, testRunner=runner).这样做,您将 unittests 参数更改为一个(不发生错误)到包含真实参数的列表。请注意,此列表的末尾是包含测试参数新值的字典。

好的,现在你写了一个函数装饰器,它应该看起来像这样:

def load_params(system_arguments_list):
def decorator(func_to_decorate):
@wraps(func_to_decorate)
def wrapper(self, *args, **kwargs):
kwargs = system_arguments_list[-1]
return func_to_decorate(self, **kwargs)
return wrapper
return decorator

并以这种方式使用此装饰器:

@classmethod
@load_params(sys.argv)
def setUpClass(cls, ip="11.111.111.111",
browserType="Chrome",
port="4444",
h5_client_url="https://somelink.com/",
h5_username="username",
h5_password="pass"):
cls.driver = get_remote_webdriver(ip, port, browserType)
cls.driver.implicitly_wait(30)
cls.h5_client_url = h5_client_url
cls.h5_username = h5_username

最新更新