iOS KIF自动化测试

作者: 当前明月 | 来源:发表于2018-05-25 13:26 被阅读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选项要勾上才行。

    相关文章

      网友评论

        本文标题:iOS KIF自动化测试

        本文链接:https://www.haomeiwen.com/subject/wmppdftx.html