如何执行没有副作用的外部python脚本?

时间:2018-10-29 02:39:42

标签: python testing

我正在尝试使用Python3构建一种简单的DSL(特定于域的语言)以进行特殊的测试。 DSL基础结构将定义一些测试命令,然后运行根据这些命令编写的外部Python脚本,但也可能包含任何其他有效的Python。

第一个问题是独立运行外部脚本,而不会在脚本循环执行时累积一个脚本对另一个脚本的副作用。

第二个问题是执行外部脚本本身定义的函数(例如on_setup())。这些功能需要在DSL解释器级别执行。

以下是测试框架的基本代码(“ cutest.py”):

# DSL command
def test(title):
    print("test:", title)
    try:
        on_setup() # function from the current test
    except:
        print("on_setup() not found")

# DSL command
def expect(str):
    print("expect:", str)

# other DSL commands...

def main():
    import glob
    scripts = glob.glob("test*.py")
    for fname in scripts:
        print("*******", fname)
        try:
            exec(open(fname).read(), globals())
        except:
            print("errors in script:", fname)

if __name__ == "__main__":
    main()

这是“ test_1.py”脚本:

def on_setup():
    print("test_1.py:on_setup")

test("My first test")
expect("foo")

最后,这是“ test_2.py”脚本:

test("My second test")
expect("bar")

请注意,“ test_2.py”没有定义其on_setup()函数。

现在,当我在具有python cutest.pytest_1.py的目录中运行test_2.py时,将得到以下输出:

******* test_1.py
test: My first test
test_1.py:on_setup
expect: foo
******* test_2.py
test: My second test
test_1.py:on_setup
expect: bar

问题是test_2.py的输出显示“ test_1.py:on_setup”(运行test_1.py的副作用,而它应显示“ on_setup()not found”,因为{{ on_setup()中未定义1}}。

在我的框架代码“ cutest.py”中,我使用了Python test_2.py调用,但是也许可以使用exec(.., globals())或其他某种机制来解决问题。

1 个答案:

答案 0 :(得分:0)

我找到了一种可以使它工作的可接受方法,并且我想知道Python专家对它的看法。

因此,这是修改后的“ DSL解释器”代码(“ cutest.py”):

# DSL command
def test(title):
    print("test:", title)
    global glb_dict
    try:
        glb_dict['on_setup']() # function from the current test
    except:
        print("on_setup() not found")

# DSL command
def expect(str):
    print("expect:", str)

# other DSL commands...

def main():
    import glob
    scripts = glob.glob("test*.py")
    global glb_dict
    for fname in scripts:
        glb_dict = {
            "test": test,
            "expect": expect
            # other commands...
        }
        print("*******", fname)
        try:
            exec(open(fname).read(), glb_dict)
        except:
            print("errors in script:", fname)

if __name__ == "__main__":
    main()

第一个更改是使用全局字典glb_dict而不是globals()。为每个测试脚本初始化glb_dict字典,以便从以前的运行中消除任何副作用。

第二个更改是对特定于测试的on_setup()函数的调用,该函数现在从glb_dict字典开始,如下所示:glb_dict['on_setup']()

修改后的cutest.py代码执行相同的两个测试脚本,如下所示:

python cutest.py

******* test_1.py
test: My first test
test_1.py:on_setup
expect: foo
******* test_2.py
test: My second test
on_setup() not found
expect: bar

具体来说:(1)找到“ test_1.py:on_setup”函数,(2)在test_2.py中找不到“ on_setup”函数(因为它不存在)。