用于调用TKinter GUI的Unittest

Mic*_*udl 6 python user-interface unit-testing tkinter python-2.7

假设一个脚本启动TKinter GUI(例如scripts/launch_GUI.py),并且是PyPI包的一部分(例如MyPackage).

.
??? appveyor.yml
??? MyPackage
?   ??? TkOps.py
?   ??? CoreFunctions.py
??? README.md
??? requirements.txt
??? scripts
?   ??? launch_CLI.py
?   ??? launch_GUI.py
??? setup.py
??? tests
    ??? MyPackage_test.py
Run Code Online (Sandbox Code Playgroud)

启动脚本非常简约:

#!/usr/bin/env python2
if __name__ == '__main__':
    import sys, os
    sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'MyPackage'))
    import TkOps
    TkOps.start_GUI()
Run Code Online (Sandbox Code Playgroud)

什么单元测试,你会建议,以评估是否使用TKinter GUI被正确启动时启动launch_GUI.py

注意:我只想评估启动脚本是否完成其工作并启动GUI,而不是用户是否可以与GUI交互.

Dim*_*nek 4

可能有人会说您需要功能测试而不是单元测试,但无论如何让我们尝试一下!

虽然可以通过 via 测试启动脚本exec(),但这被认为是不好的做法。让我们重构它:

def main():
    import sys, os
    sys.path.append(os.path.join(os.path.dirname(__file__), '..', 'MyPackage'))
    import TkOps
    TkOps.start_GUI()

if __name__ == '__main__':
    main()
Run Code Online (Sandbox Code Playgroud)

然后我们来确定单元测试应该测试什么,例如:

  • sys.path已更新为正确的路径MyPackage
  • start_GUI叫做

那么mokist [1] 单元测试可能如下所示:

@mock.patch("sys.path", copy.copy(sys.path))
@mock.patch.dict(sys.modules, TkOps=mock.MagicMock())
def test_main():
    main()
    # minimal validation of sys.path side effect
    # ideally this would check that path bit points to real directory
    assert any(p.endswith("/MyPackage") for p in sys.path)
    # validation of expected call
    assert sys.modules["TkOps"].start_GUI.called
Run Code Online (Sandbox Code Playgroud)

经典的单元测试需要 GUI 中的逃生舱口,例如:

def start_GUI(dry_run=False):
    import tk
    ...
    if not dry_run: tk.foobar()
Run Code Online (Sandbox Code Playgroud)

[1] https://agilewarrior.wordpress.com/2015/04/18/classical-vs-mockist-testing/