MixboxMocksRuntime 0.3.46

MixboxMocksRuntime 0.3.46

Artyom RazinovTimofey SoloninAlexey ShpirkoArtyom RazinovVladislav Alekseev 维护。



 
依赖
MixboxGenerators>= 0
MixboxTestsFoundation>= 0
 

  • Avito 的代码蜂巢

概述

Version License Build Status

强大的适用于 iOS 的端到端 UI 测试框架。

目前它在 Avito 中使用,我们已经拥有 700+ 的端到端 UI 测试,其中约 90% 是成功的,并帮助我们减少了两年的人工测试。我们在 PR 上运行大约 25%,并且正在努力实现所有测试在 pull request 上执行,部分是通过将黑盒 E2E 测试切换到灰盒测试。我们在 3 个平台上运行这些测试,花费大约 40 分钟(测试总时长为 30+ 小时),因为我们使用了 Emcee,一个能够在多台机器上运行测试的测试运行器(请注意,Mixbox 不需要 Emcee)。我们也在编写灰盒测试(在这个测试中我们模拟类、网络等一切),但我们刚刚开始。

如果您对在您的公司使用它感兴趣,请提交给我们一个问题。我们正在努力使其成为社区可用的,然而,这并不是我们的主要目标。

功能

  • 动作和检查(显然)

  • 像素可见性检查

  • 一切都有轮询

  • 完全自动滚动

  • 黑盒和灰盒测试!

    • 黑盒测试在单独的应用程序中运行,并且能够启动应用程序。您可以使用此类测试测试更多应用程序功能。您可以使用模拟,但这将要求您编写更多代码(使用启动参数或实现进程间通信)。
    • 灰盒测试在应用内部运行(例如EarlGrey),但测试与黑盒测试具有兼容性,因此您可以共享测试模型、页面对象、测试辅助程序等。您可以轻松地进行任何模拟,因为测试在相同进程中执行。不使用模拟就无法开始测试应用程序。

    大部分代码在灰盒和黑盒测试之间共享,因为大部分功能。两种选项都有自己的好处。使用这两种方法以获得测试金字塔

  • 页面对象

    • 可以在其中包含任意代码的函数
    • 页面对象元素可以嵌套元素(但是,它需要一些看起来不太好的样板代码)
    • 一切(动作/检查)都是完全可扩展的。如果您实现自定义动作或检查,它将自动适用于黑盒和灰盒测试(请参阅SwipeAction,所有内置动作实际上是扩展)。
  • UICollectionView中的每个单元格都在测试中可见(包括屏幕外的单元格)

  • 自定义应用程序和测试之间的进程间通信

  • 自定义测试中可见的视图的值

  • 网络模拟(通过NSURLSessionProtocol

  • 设置权限(相机/地理位置/通知等)

  • 推送通知的模拟(限制:仅限于活动应用!)

  • 从测试中打开URL

  • 地理位置的模拟

  • 硬件键盘(定义了非常少的键码,但是可以轻松实现)

  • 可在不影响分叉仓库的情况下自定义

  • Swift & Objective-C

  • 经过测试

    • 在3种设备配置上进行了176项黑盒UI测试
    • 在3种设备配置上进行了155项灰盒UI测试
    • 在4种设备配置上进行了100项单元测试
    • SwiftLint +自定义检查器
    • 所有测试都针对每次将提交推送到Mixbox进⾏执⾏,通常1 PR等于1次提交。
    • 使用5个版本的Xcode(10.0,10.1,10.2.1,10.3,11.0)对该程序的2个演示进行了测试。
  • 可配置报告(例如:Tests项目与Allure集成,Allure是一个具有Web UI的开源报告系统,Avito我们使用自研解决方案进行报告;您可以实现自己的实现)

正在开发中/尚未开源

  • 页面对象的代码生成
  • 获取应用程序中所有断言失败
  • 用于与Springboard一起工作的外观
  • 在不同生产版本和测试版本之间切换可访问性值

安装

使用Mixbox有两种方式。

第一种是演示中描述的,它过于简化,基本上您只需使用pod SomePod

第二种我们在Avito中使用,看起来像这样:Tests(在那里查看Podfile)。

文档还不够充分,因此您可以尝试将Mixbox链接到简单的方法(演示),但使用Tests中的代码示例。

支持的 iOS/Xcode/Swift 版本

  • Xcode 11
  • Swift 5
  • iOS 10.3, iOS 11.4, iOS 12.1,中间版本可能正常或不正常,所述版本已在 CI 上测试
  • Cocoapods 1.8.4
  • Mac OS 10.14.6

不再支持 Xcode 9/10 及更早版本。如果您计划在不同环境中使用此项目并遇到问题,请告知我们。

已知问题

  • 在 iOS 11.2 上崩溃(iOS 11.3、iOS 11.4 上运行正常)
  • 在物理设备上设置权限不起作用(也许在其他方面也不行,我们未在物理设备上测试;基本功能正常)
  • 未测试设备旋转,我认为我们在这方面有虫子
  • 未测试 iPad
  • 报告中使用俄语(将很快修复)

示例

有关实际示例,请参阅 Tests 项目。它是使用它的最新开源示例,但不太真实(不展示如何为真实应用程序编写测试)。

显示基本功能的测试示例

func test() {
    // Setting permissions
    permissions.camera.set(.allowed)
    permissions.photos.set(.notDetermined)

    // Functions are useful in page objects and allows
    // reusing code, for example, for transitions between states of the app
    pageObjects.initial
        .authorize(user: testUser)
        .goToCvScreen()
        
    // Aliases for simple assertions (you can add your own):
    pageObjects.simpleCv.view.assertIsDisplayed()
    pageObjects.simpleCv.title.assertHasText("My CV")
    
    // Fully customizable assertions
    pageObjects.simpleCv.addressField.assertMatches { element in
        element.text != addressFieldInitialText && element.text.isNotEmpty
    }
    
    // Network stubbing.
    networking.stubbing
        .stub(urlPattern: ".*?example.com/api/cv")
        .thenReturn(file: "cv.json")
    // There is also a monitoring feature, including recording+replaying feature that
    // allows to record all network and replay in later, so your tests will not require internet.
    
    // Actions
    pageObjects.simpleCV.occupationField.setText("iOS developer")
    pageObjects.simpleCV.createCVButton.tap()
}

声明页面对象

public final class MapScreen:
    BasePageObjectWithDefaultInitializer,
    ScreenWithNavigationBar // protocol extensions are very useful for sharing code
{
    // Basic locator  
    public var mapView: ViewElement {
        return element("Map view") { element in
            element.id == "GoogleMapView"
        }
    }
    
    // You can use complex checks
    // Note that you can create your own matchers like `element.isFooBar()`
    public func pin(coordinates: Coordinates, deltaInMeters: Double = 10) -> ViewElement {
        return element("Pin with coordinates \(coordinates)") { element in
            element.id == "pin" && element
                .customValues["coordinates", Coordinates.self]
                .isClose(to: coordinates, deltaInMeters: deltaInMeters)
        }
    }
}

声明自定义页面对象元素

public final class RatingStarsElement:
    BaseElementWithDefaultInitializer,
    ElementWithUi
{
    public func assertRatingEqualsTo(
        _ number: Int,
        file: StaticString = #file,
        line: UInt = #line)
    {
        assertMatches(file: file, line: line) { element in
            element.customValues["rating"] == number
        }
    }
}

粘贴的代码

这个库包含从其他库复制的部分代码。有时候是单个文件,有时是因为我们需要在源代码中内置条件编译,以防止在发布版本中链接代码。

  • EarlGrey(使用 EarlGrey 的每个源文件都包含 EarlGrey 子串)。[许可证在此(Apache)](而易古尔埃尔格雷_parallel_license/LICENSE)。它是可见性检查器,设置可访问性等。原始库:https://github.com/google/EarlGrey
  • AnyCodable。添加了 #if 条件语句。原始库:https://github.com/Flight-School/AnyCodable
  • SBTUITestTunnel。有版本号大于3.0.6的 webView 的一个错误。然后在几年后,我们在构建它时遇到了问题时断时续。解决方法非常原始 - 复制粘贴一切以避免问题。我们本来可以深入研究,但我们有计划将来使用原生的 IPC 解决方案,所以我们就此为止。原始库:https://github.com/Subito-it/SBTUITestTunnel
  • CocoaImageHashing。我们需要一个不能因为向后兼容性问题合并的修复(因[a问题](https://github.com/ameingast/cocoaimagehashing/issues/13))。由于我们不需要向后兼容性,所以我们使用了复制的代码。原始库:https://github.com/ameingast/cocoaimagehashing

用于测试

其他文档