程序猿阵线联盟-汇总各类技术干货自动化测试我爱编程

iOS KIF自动化测试

2018-05-25  本文已影响118人  当前明月
一. iOS单元测试,UI测试基本介绍
二. KIF简介
三. KIF集成
四. 测试用例编写
五. jenkins集成步骤
六. 总结
一 iOS单元测试,UI测试基本介绍
1.1 简单介绍

iOS有两个层次的测试:单元测试,UI测试。
单元测试:XCTest,XCTest最后生成的是一个bundle。bundle是不能直接执行的,必须依赖于一个宿主进程。XCTest主要基础功能:异步测试,性能测试,代码覆盖率等。
UI测试:UI Testing,UI测试是模拟用户操作,进而从业务处层面测试,iOS UI测试还有一个核心功能是UI Recording。选中一个UI测试用例,然后点击图中的小红点既可以开始UI Recoding,录制完成之后,会自动生成一段测试代码。

1.2 项目中如何集成

如果是一个新项目,在创建项目的时候,直接勾选 include Unit Tests,和include UI Tests 即可,如下图:


iOS 新项目如何加入单元测试和UI测试.png
1.2 已有项目中如何集成

如果我们有一个已有项目,可能前期没有加入测试框架,那么后期我们如何引入呢,步骤如下图:

步骤一 :点击项目工程,在配置文件右下角点击+号会弹出一个选择框

步骤一

步骤二 :下滑到test一栏,这里就找到了单元测试和UI测试,这里我们选择iOS UnitTesing Bundle

步骤二
步骤三 :填写一些基本信息,
步骤三
步骤四 :添加成功的页面,Testable SwiftTests目录就是就是我们刚生成的,今后的测试用例也都是在这个目录下面写。
步骤四
总结:这里只是简单的介绍iOS测试方面的一些东西,我们今天的主要目的是讲一个第三方的UI测试框架,以及如何结合jenkins做自动化测试,所以这里就不详细介绍了,下面开始介绍我们的主题。
二. KIF简介

2.1 简要说明
KIF代表Keep It Functional,是一款iOS集成测试框架。 通过利用操作系统为具有视觉障碍的用户提供的辅助功能属性,可以轻松实现iOS应用程序的自动化。

KIF使用标准的XCTest测试目标来构建和执行测试。 测试在主线程中同步进行(运行运行循环以强制时间流逝),从而允许更复杂的逻辑和组合。 这也使得KIF能够利用Xcode Test Navigator,命令行构建工具和Bot测试报告。

KIF使用未公开的Apple API。 大多数iOS测试框架都是如此,并且对于测试目的而言是安全的,但重要的是KIF不会将其转换为生产代码,因为它会让您的应用程序提交被Apple拒绝。 按照下面的说明确保KIF为您的项目配置正确。

KIF是基于XCTest的一个第三方UI测试框架,XCTest是iOS的单元测试框架,所以项目中加入XCTest框架可以做单元测试,又通过引入KIF框架做UI集成测试。

2.2 功能特性
1 最小化间接性
所有的KIF测试都是用Objective-C编写的。 这可以最大程度地集成代码,同时最大限度地减少必须构建的图层数量。

2 简单的配置
KIF直接集成到您的Xcode项目中,因此无需运行其他Web服务器或安装任何其他软件包。

3 宽操作系统和Xcode覆盖
KIF的测试套件正在针对iOS 8+和Xcode 7+运行。 较低的版本可能仍然有效,但你的里程可能会有所不同。 我们尽最大努力保留向后兼容性。

4 像用户一样测试
KIF试图模仿实际的用户输入。 尽可能使用触摸事件来完成自动化。

5 与Xcode测试工具自动集成
您可以使用测试导航器轻松运行单个KIF测试,或者使用机器人启动每晚验收测试。

三. KIF集成

我们通过cocopod来进行引入
步骤一
项目中要先引入XCTest,引入步骤和方法,可以参考本文上面(1.2 已有项目中如何集成 )章节

步骤二
打开工程里的Podfile文件加入以下代码:

target 'MyApp' do
    pod 'Alamofire'
    pod 'SwiftProgressHUD'
    pod 'WechatOpenSDK'
    pod 'Bugly'
end
target 'MyAppTests' do
     pod 'KIF'
end

这里要注意target是项目的Tests,不要加错位置了,当初我就加错了加到target "MyApp",然后在写测试用例是引入KIF.h,总是报错,可能当时没太注意这个细节,结果掉坑里了。编辑完成,pod install 一下。

步骤三

1: 项目名Tests对象 (项目名+Tests)---> Build Phase ---> Target Dependencies ---> "+" --->"项目的Tests文件"(去百度一下这个 tests 文件 和UItests 文件有什么区别)

2: 项目名Tests对象 ---> Build Settings ---> Linking(直接搜)---> Bundle Loader 填写"$(BUILT_PRODUCTS_DIR)/项目名称.app/项目名称"

3: 项目名Tests对象 ---> Build Settings ---> Wrapper Extension (直接搜)设置成 "xctest"

4: 点击你 RUN 按钮前面的前面的项目target ---> Edit Scheme... ---> Test 看看里面有没有你要测试的项目,没有就添加

步骤四
在Tests目录下创建一个桥接文件(创建桥接文件,可以在当前目录下新建一个oc文件,xcode中途会提示是否创建桥接文件,桥接文件创建完成后,再把oc文件删除就行了),KIF是OC写的,用swift写测试用例就要创建一个桥接文件,oc的话就不用了。

步骤四
总结:自此,KIF我们就已经集成完毕了,下面就开始我们测试用例的编写了。
四. 测试用例编写

我们写了一个登陆流程的示例:新建一个LoginTest.swift文件有几个注意点:
1 要导入KIF头文件 import KIF
2 底层没有提供tester方法,所以要加一个扩展
3 类要继承 KIFTestCase类
4 tester().usingLabel("login_phone"),使用usingLabel获取控件,前提是项目中这个控件的要设置accessibilityLabel 属性

image.png
LoginTests.swift

import XCTest
import KIF

extension XCTestCase {
    func tester(_ file : String = #file, _ line : Int = #line) -> KIFUIViewTestActor {
        return KIFUIViewTestActor(inFile: file, atLine: line, delegate: self)
    }
    
    func system(_ file : String = #file, _ line : Int = #line) -> KIFSystemTestActor {
        return KIFSystemTestActor(inFile: file, atLine: line, delegate: self)
    }
}
class LoginTests: KIFTestCase {

    func testLogin(){
        noInputLogin()
        noValidateLogin()
        validateLogin()
        agreeValidateLogin()
    }
    
    func testAdd() {
        let a = 3
        let b = 4
        XCTAssert(a+b == 7, "计算正确")
    }
    func testnoValidateLogin(){
        
        let userNameInput = tester().usingLabel("login_phone")
        userNameInput?.enterText("15856885688")
        let loginBtn =  tester().usingLabel("登录")
        loginBtn?.tap()
        tester().wait(forTimeInterval: 2)
    }
    
    func noInputLogin(){
        let loginBtn =  tester().usingLabel("登录")
        loginBtn?.tap()
        tester().wait(forTimeInterval: 2)
    }
    
    func noValidateLogin(){
        
        let userNameInput = tester().usingLabel("login_phone")
        userNameInput?.enterText("15856885688")
        let loginBtn =  tester().usingLabel("登录")
        loginBtn?.tap()
        tester().wait(forTimeInterval: 2)
        
    }
    
    func validateLogin(){
        let invalicaodeInput = tester().usingLabel("login_input_invlicode")
        invalicaodeInput?.enterText("123456")
        let valicodeBtn = tester().usingLabel("获取验证码")
        valicodeBtn?.tap()
        let loginBtn =  tester().usingLabel("登录")
        loginBtn?.tap()
        tester().wait(forTimeInterval: 2)
    }
    
    func agreeValidateLogin(){
        
        let login_agree = tester().usingLabel("login_agree")
        login_agree?.tap()
        let loginBtn =  tester().usingLabel("登录")
        loginBtn?.tap()
        let firstPage = tester().usingLabel("首页").waitForView()
        if  (firstPage != nil) {
            loginOut()
        } else {
            XCTAssert(false, "未找到页面")
        }
    }
    
    func loginOut(){
        let meBtn = tester().usingLabel("我")
        meBtn?.tap()
        
        let setUpBtn = tester().usingLabel("设置")
        setUpBtn?.tap()
        
        let outBtn = tester().usingLabel("退出登录")
        outBtn?.tap()
        
        tester().wait(forTimeInterval: 5)
    }
}

所有的测试方法要以test头,不以test开头的方法,测试是不会执行的,但可以作为内置方法,其他的测试方法可以调用。这里只做一个示例具体使用请参考官方文档:https://github.com/kif-framework/KIF,官方demo它提供了如下一些操作示例:

官方demo示例,列表操作,滑动操作,文本,选择框,刷新,长按等等
到此KIF集成,使用流程,我们基本介绍完了。下面我们看下如何结合jenkins做自动化测试
五. jenkins集成步骤

步骤一
首先我们要把已经完成的测试用例的项目上传到一个git仓库里。
步骤二
1 启动jenkins,新建item,构建一个自由风格的项目,输入名称点击确定,接下来就是job配置。

新建item
2 主要配置后五项,源码管理,构建触发器,构建环境,构建,构建后操作。
项目配置

3 源码管理


源码管理

这里就是填写你的仓库路径,授权账户,分支。

4 构建触发器


构建触发器

这里根据不同的需求,可以自定义触发脚本运行时机。这里设置构建触发器*/2 * * * *,每2分钟检查一次源码变化。

5 构建环境
此项可不用配置

6 构建
增加构建步骤,选择Execute 脚本

image

输入脚本:

#!/bin/bash -l

  #新建目录用于保存报告

  mkdir test-reports

  #pod可能失败的全局参数设置

  export LANG=en_US.UTF-8

  export LANGUAGE=en_US.UTF-8

  export LC_ALL=en_US.UTF-8

  pod install

  #xcodebuild test -workspace XXX.xcworkspace -scheme XXXTests -destination 'platform=iOS Simulator,name=iPhone 6s'跑[<u style="margin: 0px auto; padding: 0px; font-family: &quot;microsoft yahei&quot;;">**测试用例**</u>](javascript:;)

  #-enableCodeCoverage YES 收集[<u style="margin: 0px auto; padding: 0px; font-family: &quot;microsoft yahei&quot;;">**测试覆盖率**</u>](javascript:;)

  #ocunit2junit 输出报告转换为jenkins可读的[<u style="margin: 0px auto; padding: 0px; font-family: &quot;microsoft yahei&quot;;">**junit**</u>](javascript:;)报告

  xcodebuild test -workspace XXX.xcworkspace -scheme XXXTests -destination 'platform=iOS Simulator,name=iPhone 6s' -configuration Debug -enableCodeCoverage YES 2>&1 | ocunit2junit

  #slather coverage转换覆盖率报告为html文件,jenkins可读

  #--input-format profdata  xcode生成的为profdata格式的文件,转换为html以便jenkins显示

  #--ignore 排除筛选需要计算的文件,多个格式写多个ignore表达式

  slather coverage --html --input-format profdata --binary-basename XXXApp --scheme XXXTests --workspace XXX.xcworkspace --configuration Debug --ignore **View** --ignore **AppText** --output-directory reports XXX.xcodeproj

这里用到两个工具, ocunit2junit 以及slather.
打开mac终端安装

sudo gem install ocunit2junit
sudo gem install slather

7 构建后操作
读取显示junit和覆盖率html报告
  这里用到两个jenkins插件,jenkins->系统管理-> 管理插件,找到JUnit Plugin和HTML Publisher plugin,安装重启jenkins,如果没安装这两个插件的话,构建后操作步骤是没有这两个选项的

选择Publish Junit test result report,配置xml文件路径为第三步配置的test-reports/*.xml。

junit结果报告

再增加一个构建后操作,选择Publish HTML reports, 配置html路劲为第三步配置的reports,Index文件为index.html,可以设置标题Reports title为Coverage Report。

HTML覆盖率报告配置

保存返回,点击立即构建,等待构建完成,返回job主页,可以看到junit测试结果报告和覆盖率的图表了。


UI自动化构建结果

到此整个jenkins集成完毕了,以后就可以愉快的跑UI测试了

六. 总结

项目中对于单元测试,UI测试我们可以单独拉取一个分支,专门作为测试分支,每次代码提交前,先合并到这个测试分支,然后jenkins就会开始跑你所有的测试用例,如果我们写了很多测试用例,有很多个测试用例文件,我们要指定跑哪几个怎么办,看下图:


image.png

EditScheme->Test
把你不想跑的测试用例直接勾掉就行了,然后保存推送到git仓库就行了,这里还有一个注意的,上文讲的覆盖率报告的生成,这里有个Code Coverage选项要勾上才行。

上一篇下一篇

猜你喜欢

热点阅读