python - 测试kivy编写的应用程序时如何与UI交互?

标签 python kivy kivy-language

该应用程序由 kivy 编写。 我想通过 pytest 测试一个函数,但为了测试该函数,我需要先初始化该对象,但该对象在初始化时需要 UI 中的某些内容,但我处于测试阶段,所以不知道如何从 UI 中检索一些内容。

这是有错误并已被处理的类

class SaltConfig(GridLayout):
    def check_phone_number_on_first_contact(self, button):
        s = self.instanciate_ServerMsg(tt)

        try:
            s.send()
        except HTTPError as err:
            print("[HTTPError] : " + str(err.code))
            return

        # some code when running without error

    def instanciate_ServerMsg():
        return ServerMsg()

这是生成前一个类使用的 ServerMsg 对象的辅助类。

class ServerMsg(OrderedDict):
    def send(self,answerCallback=None):
        #send something to server via urllib.urlopen

这是我的测试代码:

class TestSaltConfig:
    def test_check_phone_number_on_first_contact(self):
        myError = HTTPError(url="http://127.0.0.1", code=500,
                        msg="HTTP Error Occurs", hdrs="donotknow", fp=None)

    mockServerMsg = mock.Mock(spec=ServerMsg)
    mockServerMsg.send.side_effect = myError

    sc = SaltConfig(ds_config_file_missing.data_store)

    def mockreturn():
        return mockServerMsg

    monkeypatch.setattr(sc, 'instanciate_ServerMsg', mockreturn)
    sc.check_phone_number_on_first_contact()

我无法初始化该对象,它会在初始化时抛出 AttributeError,因为它需要来自 UI 的一些值。

所以我陷入困境。

我尝试模拟该对象,然后将函数修补到原始函数,但也不起作用,因为函数本身具有与 UI 相关的逻辑。

如何解决?谢谢

最佳答案

我写了一篇关于使用简单的运行者测试 Kivy 应用程序的文章 - KivyUnitTest 。它与 unittest 一起使用,而不是与 pytest 一起使用,但重写它应该不难,这样它就可以满足您的需求。在本文中,我解释了如何“渗透”UI 主循环,这样您就可以愉快地使用按钮执行以下操作:

button = <button you found in widget tree>
button.dispatch('on_release')

还有更多。基本上你可以通过这样的测试做任何事情,并且不需要独立测试每个功能。我的意思是……这是一个很好的做法,但有时(主要是在测试 UI 时),您不能只是将其撕下来并放入一个漂亮的 50 行测试中。

通过这种方式,您可以执行与临时用户在使用您的应用程序时所做的完全相同的操作,因此您甚至可以发现在测试临时方式时遇到的问题,例如一些奇怪/意外的用户行为。

这是骨架:

import unittest

import os
import sys
import time
import os.path as op
from functools import partial
from kivy.clock import Clock

# when you have a test in <root>/tests/test.py
main_path = op.dirname(op.dirname(op.abspath(__file__)))
sys.path.append(main_path)

from main import My


class Test(unittest.TestCase):
    def pause(*args):
        time.sleep(0.000001)

    # main test function
    def run_test(self, app, *args):
        Clock.schedule_interval(self.pause, 0.000001)

        # Do something

        # Comment out if you are editing the test, it'll leave the
        # Window opened.
        app.stop()

    def test_example(self):
        app = My()
        p = partial(self.run_test, app)
        Clock.schedule_once(p, 0.000001)
        app.run()

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

但是,正如 Tomas 所说,您应该尽可能将 UI 和逻辑分开,或者更好地说,当这是一件高效的事情时。您不想仅仅为了测试需要与 UI 通信的单个功能而模拟整个大型应用程序。

关于python - 测试kivy编写的应用程序时如何与UI交互?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40665867/

相关文章:

python - 根据输入设置变量值,StringProperty kivy

python - Kivy DragBehavior 属性——最简单的方法。为什么它不起作用?

python - Kivy 颜色解析器无效的颜色格式

python - 403 Forbidden while trying to display image from url - Kivy

python - 如何在Kivy中使用KivyMD字体

python - 如何在Python中打印程序的返回

python - 使用 Cython 将结构从 C 返回到 Python

python - 使用 NaN 获取 pandas 系列模式的最快方法

Python kwargs 从其他参数中获取值

python - Kivy Python-文本输入框填充整个 float 布局屏幕