gpt4 book ai didi

ios - XCUITest:如何跳入应用程序代码?如何修改被测应用程序的状态?

转载 作者:行者123 更新时间:2023-12-02 00:12:31 28 4
gpt4 key购买 nike

来自Android/Espresso背景,我仍在为XCUITest和UI测试进行挣扎。
我的问题是关于两个相关但截然不同的问题:

  • 如何针对被测应用程序的源进行编译和链接?
  • 如何跳入被测应用程序的方法并在运行时修改其状态?

  • 为了解决这些问题,我们首先应该了解XCode的“单元测试目标”和“UI测试目标”之间的区别。
  • XCUITests在完全独立的进程中运行,无法跳入被测应用程序的方法。此外,默认情况下,XCUITests不会链接到被测应用程序的任何来源。
  • 相反,XCode的单元测试与应用程序源链接在一起。也可以选择执行“@testable导入”。从理论上讲,这意味着单元测试可以跳转到任意应用程序代码中。但是,单元测试不会针对实际的应用程序运行。而是,单元测试针对没有任何UI的精简版iOS SDK运行。

  • 现在,针对这些约束有不同的解决方法:
  • 将一些选定的源文件添加到UI测试目标。这不能调用应用程序,但是至少它可以在应用程序和UI测试之间共享选定的代码。
  • 通过CommandLine.arguments将启动参数从UI测试传递到被测应用。这样可以将特定于测试的配置应用于要测试的应用。但是,这些启动参数需要由应用程序解析和解释,这导致测试代码对应用程序造成污染。此外,启动参数只是更改被测应用程序行为的一种非交互方式。
  • 实现仅XCUITest可以访问的“调试UI”。同样,这具有污染应用程序代码的缺点。

  • 这导致了我的结论性问题:
  • 存在哪些替代方法可以使XCUI测试更强大/更动态/更灵活?
  • 是否可以针对整个应用程序源和所有pod依赖项而不是仅几个选定文件来编译和链接UI测试?
  • 是否有可能获得Android的工具化测试+ Espresso的强大功能,使我们可以在被测试的应用程序上执行任意状态修改?

  • 为什么我们需要这个

    响应@theMikeSwan,我想阐明我对UI测试体系结构的立场。

    UI Tests should not need to link to app code, they are designed to simulate a user tapping away inside your app. If you were to jump into the app code during these tests you would no longer be testing what your app does in the the real world you would be testing what it does when manipulated in a way no user ever could. UI tests should not have any need of any app code any more than a user does.



    我同意以这种方式操纵应用程序是一种反模式,只应在极少数情况下使用。
    但是,对于可能的情况,我有非常不同的立场。
    我认为,UI测试的正确方法不是黑盒测试,而是灰盒测试。尽管我们希望UI测试尽可能地具有黑匣子,但在某些情况下,我们还是希望深入了解被测应用程序的实现细节。
    仅举几个例子:
  • 可扩展性:没有UI测试框架可以为每个用例提供API。项目要求不同,有时我们想编写自己的函数来修改应用程序状态。
  • 内部状态断言:我希望能够为应用程序状态编写自定义断言(不仅仅依赖UI的断言)。在我当前的Android项目中,我们有一个臭名昭著的子系统。我用自定义方法断言了这个子系统,以防止回归错误。
  • 共享的模拟对象:在我当前的Android项目中,我们具有无法用于UI测试的自定义硬件。我们用模拟对象替换了此硬件。我们直接从UI测试中对那些模拟对象运行断言。这些断言通过共享内存无缝地工作。而且,我不想使用所有模拟实现来污染应用程序代码。
  • 将测试数据保留在外面:在我当前的Android项目中,我们将测试数据直接从JUnit加载到应用程序中。使用XCUITest的命令行参数,这将受到更大的限制。
  • 自定义同步机制:在我当前的Android项目中,我们具有围绕多线程基础结构的包装器类,以将UI测试与后台任务同步。没有共享内存(例如Espresso IdlingResources),很难实现这种同步。
  • 普通代码共享:在我当前的iOS项目中,我为上述启动参数共享一个简单的定义文件。这样就可以以类型安全的方式传递启动参数,而无需复制字符串文字。尽管这是一个较小的用例,但仍表明选择的代码共享可能很有值(value)。

  • For UI tests you shouldn't have to pollute your app code too much. You could use a single command line argument to indicate UI tests are running and use that to load up some test data, login a test user, or pick a testing endpoint for network calls. With good architecture you will only need to make the adjustment once when the app first launches with the rest of your code oblivious that it is using test data (much like if you have a development environment and a production environment that you switch between for network calls).



    这正是我在当前的iOS项目中正在做的事情,而这正是我要避免的事情。
    尽管好的架构可以避免过多的破坏,但这仍然是对应用程序代码的污染。而且,这并不能解决我上面强调的任何用例。
    通过提出这样的解决方案,您实际上可以接受根本的黑盒测试不如灰盒测试。
    与生活的许多部分一样,差异化的观点比激进的“要好用只使用我们为您提供的工具,您无需这样做”要好。

    最佳答案

    UI测试不需要链接到应用程序代码,它们旨在模拟用户在您的应用程序内部轻敲。如果您要在这些测试中跳入应用程序代码,则不再需要测试您的应用程序在现实世界中的功能,而是在测试以任何用户无法操纵的方式操作时的功能。与用户相比,UI测试不需要任何应用程序代码。

    当然,对于单元测试和集成测试,您可以使用@testable import …来访问未标记为privatefileprivate的任何方法和属性。从测试代码中仍然无法访问标记为privatefileprivate的所有内容,但包括internal在内的所有其他内容都将可访问。在这些测试中,您应该有意地添加一些在现实世界中不可能发生的数据,以确保您的代码可以处理它。这些测试仍不应进入方法并进行任何更改,否则该测试将不会真正测试代码的行为。

    您可以在项目中创建任意数量的单元测试目标,并且可以使用这些目标中的一个或多个来进行集成测试而不是单元测试。然后,您可以指定在不同时间运行的目标,以免较慢的集成测试不会在每次测试时都运行并降低速度。

    运行的环境单元和集成测试实际上包含了所有内容。您可以创建 View Controller 的实例,然后调用loadViewIfNeeded()进行整个 View 设置。然后,您可以测试各种导出的存在并触发它们发送 Action (请查看UIControlsendActions(for: )方法)。如果您已经设置了必要的模拟,这将使您验证当用户点击按钮A时,是否将调用发送到事物B的正确方法。

    对于UI测试,您不必过多地污染您的应用程序代码。您可以使用单个命令行参数来指示UI测试正在运行,并使用该参数来加载一些测试数据,登录测试用户或为网络调用选择测试端点。拥有良好的架构,您只需在应用程序首次启动时进行一次调整,而其他代码则不会使用测试数据(就像您在开发环境和生产环境之间进行网络调用时切换一样) )。

    如果您想了解有关测试Swift的更多信息,Paul Hudson有一本非常好的书,您可以查看https://www.hackingwithswift.com/store/testing-swift。它包含各种测试的大量示例,以及有关如何将它们分开的良好建议。

    根据您的编辑和评论进行更新:
    看起来您真正想要的是集成测试。这些在Xcode的世界中很容易错过,因为它们没有自己创建的目标。他们使用单元测试目标,但要一起测试多个项目。

    前提是您尚未在任何商店中添加privatefileprivate,则可以在“单元测试”目标中创建测试,以确保这些商店存在,然后根据需要注入(inject)文本或触发其操作,以模拟用户浏览您的应用程序。

    通常,这种测试只是从一个 View Controller 转到第二个 View Controller ,以测试在 Action 发生时是否创建了正确的 View Controller ,但是没有什么可以说不能继续进行的。

    您不会像UI测试一样获得失败测试的屏幕图像,如果您使用 Storyboard ,请确保从 Storyboard 中实例化 View Controller 。请确保您正在捕获所有导航 Controller 以及所需的导航 Controller 。

    这种方法学使您可以像浏览应用程序一样操作,同时能够处理各种方法所需的任何数据。

    如果您有一个包含10行的方法,并且想要在第7行和第8行之间调整数据,则需要对某个可模拟对象进行外部调用,然后在其中进行更改,或者使用带有进行更改的调试器命令的断点。这个断点技巧对于调试事物非常有用,但是我不认为我会在测试中使用它,因为删除断点会破坏测试。

    关于ios - XCUITest:如何跳入应用程序代码?如何修改被测应用程序的状态?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59898746/

    28 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com