使用解析器组合器在Swift中进行高级UI测试

我一直喜欢Cucumber风格在iOS上进行UI测试。 但是我真的不喜欢在计算机上管理15000个红宝石版本,更不用说确保团队运行相同的版本,gem(我在看着你calabash-ios )等等。

我也希望它简单:只需读取代码,然后按“运行测试”即可。

因此,我决定在Swift中编写一个简单的Gherkin解析器。 我希望测试的结构如下:

 方案:导入按钮起作用 
鉴于我在主屏幕上
当我点击“导入”时
然后打开导入屏幕
  func I_am_on_the_home_screen(){ 
  ... 
}
  func the_import_screen_opens(){ 
  ... 
}

该方案位于最上方,执行功能位于其下方。 请注意,没有“ I_tap_Import”功能,我希望tap和type具有足够的通用性,以使我的框架能够理解它。

解析中

POC版本基本上是在进行字符串比较和模式匹配,但是您可以想象,这不是非常有效和灵活。

对于“真实”版本,我使用了解析器组合器。 观看Swift讨论解析数学表达式的视频时,解析器组合器引起了我极大的兴趣。

联机有一些解析器组合器的介绍,因此在这里我不会做太多详细介绍,但是它的大致工作原理是这样的:基本解析器(例如,字符)使用…悬念…组合器组合在一起! 创建更复杂的解析器( 字符串解析器= n × 字符解析器),并且可以应用一些逻辑来创建语法(字符串是直到行尾的每个字符)

我花了几天的时间来“获取”它,但是一旦我将所有内容放到白板上,一切都变得有意义。

简而言之,它解析场景时忽略了前导和尾随空格。
当有一个“ tap ”关键字时,它将使用加引号的字符串作为参数来调用预建的tap函数(例如, Given I tap on "continue"调用app.buttons["continue"].tap()

当有’ type ‘关键字时,它将使用加引号的字符串作为参数来调用预构建类型函数(例如, Given I type "hello" in field "id"调用app.textFields["id"].typeText("hello") ))

如果没有关键字,它将调用带下划线的分隔线命名函数(例如, Then I land on a page调用I_land_on_a_page()函数)

那可以让我做这样的事情:

我的测试功能

运行它

由于它是纯快速的,并且全部嵌入测试中,因此我只需要运行它,然后让测试框架和解析器完成工作即可。

除了明显的可读性优势和BDD样式测试之外,它还使我的UITests以模块化的方式结构化,从而使我可以重用许多代码。

当然,我已经将所有这些都放入了github中,因此可以随时使用它:https://gist.github.com/ijuhoor/9062f04ff3dff3ade53de77a7c4a2451