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

时间:2017-05-17 11:27:49

标签: python python-unittest

假设我在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脚本中执行此操作,因此不会对测试代码进行任何更改或只进行微小更改。

注意:我想通过batch / 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)
    

1 个答案:

答案 0 :(得分:0)

以下是一种可能的解决方案:

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

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参数更改为1(不会发生错误)到具有真实参数的列表。请注意,此列表的末尾是包含测试参数新值的字典。

好的,现在你编写一个函数装饰器,它应该是这样的:

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