久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

KIF:如何自動運行/壓力測試 iOS 應用程序以找出罕

KIF: How to auto-run/stress test an iOS app to find the cause of a rare UI bug?(KIF:如何自動運行/壓力測試 iOS 應用程序以找出罕見 UI 錯誤的原因?)
本文介紹了KIF:如何自動運行/壓力測試 iOS 應用程序以找出罕見 UI 錯誤的原因?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

限時送ChatGPT賬號..

注意:我在標題中添加了 kif 只是為了搜索索引,考慮到大部分答案都是討論它

我正在為 iOS 尋找類似 selenium 的東西,基本上是一個測試自動化/單元測試框架,它可以多次運行某個 UI 場景直到它崩潰,這將幫助我縮小導致 UI 錯誤的原因非常罕見且隨機地發生.

(順便說一句,我已經對數據源/表交互的每一行代碼進行了 NSLogged 并花費了數小時分析潛在原因……但沒有發現任何結論……再次,這個錯誤很少發生).

我查看了一些 和 KIF.我最終決定使用 KIF 同時借用 cucumber's Gherkin 語法 來描述我的單元測試.

我選擇 KIF(而不是 Frank)的原因是 KIF 是 100% 基于 obj-c,而不是使用 ruby?? 作為Frank 也是如此.所以設置更簡單,更適用于我狹隘的測試用例需求.話雖如此,我承認如果我的應用程序更復雜(即使用來自多個服務器的輸入等),Frank 會更有用.你可以看到這個優秀的最后一個季度演示文稿以了解更多關于 KIF、Frank 和其他自動化測試框架的優缺點,包括 Apple 自己的 UI 自動化.

使用 KIF 后,我發現了導致上述錯誤的錯誤,并且我可以 100% 使用 KIF 重現它!它很少發生的原因是因為它只有在我非常快地點擊屏幕時才會發生..并且由于 KIF 會自動執行這些步驟..它以非常快的速度執行它們..這暴露了錯誤:).

以下是我用于測試的代碼示例.這只是為了讓您快速了解 KIF(和 Gherkin)可以為您做什么:

在一個文件中我指定了我想要運行的場景:

- (void)initializeScenarios;{[self addScenario:[KIFTestScenario scenarioToCompleteSignInAndLoadInbox]];[self addScenario:[KIFTestScenario scenarioToFillAttachmentsWithData]];[self addScenario:[KIFTestScenario 場景ToViewAndLoadFileBucket]];[self addScenario:[KIFTestScenario 場景ToViewAndLoadFileBucketSubView]];}

每個場景都映射到步驟(要了解更多關于基于測試驅動程序開發的小黃瓜語法和行為驅動開發,我強烈建議閱讀這本關于 黃瓜):

/* @given 應用程序處于全新狀態@并且用戶已經有一個 imap 電子郵件帳戶,該帳戶具有有效的用戶名/密碼@then 用戶可以成功登錄@and 收件箱視圖將被加載@并且收件箱將加載用戶收件箱中的最新一批電子郵件*/+ (id)scenarioToCompleteSignInAndLoadInbox{KIFTestScenario *scenario =[KIFTestScenario scenarioWithDescription:@"測試一個用戶可以成功登錄."];[場景 addStepsFromArray:[KIFTestStep stepsCompleteSignInAndLoadInbox]];返回場景;}/* @假設用戶已經登錄@并且用戶已經下載了他們的文件夾@then 用戶可以點擊文件夾視圖@and 用戶可以點擊附件"遠程文件夾@and 將下載附件"遠程文件夾中的最新批次*/+ (id)scenarioToFillAttachmentsWithData {KIFTestScenario* 場景 =[KIFTestScenario scenarioWithDescription:@"測試我們可以查看附件文件夾并填寫它與數據."];[場景 addStepsFromArray:[KIFTestStep stepsToFillAttachmentsWithData]];返回場景;}/* @假設用戶已經登錄@并且用戶已經下載了他們的文件夾@and 用戶已經下載了附件@then 用戶可以點擊收件箱菜單按鈕@and 用戶可以點擊文件夾列表菜單按鈕@并且用戶可以單擊文件桶圖標(在帳戶列表視圖上)@and 文件桶的數據是從數據庫中獲取的@and 文件桶視圖顯示附件*/+ (id)scenarioToViewAndLoadFileBucket {KIFTestScenario *scenario =[KIFTestScenario scenarioWithDescription:@"測試一個用戶可以成功查看和加載文件桶父視圖"];[場景 addStepsFromArray:[KIFTestStep stepsToViewAndLoadFileBucketPage]];返回場景;}/* @假設用戶已經登錄@并且用戶已經下載了他們的文件夾@and 用戶已經下載了附件@并且用戶已經打開了文件桶視圖@then 用戶可以點擊文件桶視圖表中的隨機行@and 子視圖將從數據庫中檢索與該行相關的數據@and subview 將在 uitableview 中顯示數據*/+ (id)scenarioToViewAndLoadFileBucketSubView {KIFTestScenario *scenario =[KIFTestScenario scenarioWithDescription:@"測試一個用戶可以成功查看和加載文件桶子視圖"];[場景 addStepsFromArray:[KIFTestStep stepsToViewAndLoadFileBucketSubPage]];返回場景;}

使用 KIF 的 UI 自動化方法定義步驟(這只是一個示例):

//此步驟假設有一個附件文件夾,其中包含帶有附件的電子郵件+ (NSArray *)stepsToFillAttachmentsWithData {NSMutableArray* 步驟 = [@[] mutableCopy];【步驟添加對象:[KIFTestStep stepToTapViewWithAccessibilityLabel:@"InboxMenuButton"]];NSIndexPath* indexPath =[NSIndexPath indexPathForRow:remoteAttachmentFolderNumber inSection:0];KIFTestStep* tapAttachmentRowStep =[KIFTestStep stepToTapRowInTableViewWithAccessibilityLabel:@"附件" atIndexPath:indexPath];[步驟添加對象:[KIFTestStep stepToWaitForNotificationName:(NSString *)kBeganSyncingOlderEmails 對象:無whileExecutingStep:tapAttachmentRowStep]];[步驟 addObject:tapAttachmentRowStep];【步驟添加對象:[KIFTestStep stepToWaitForViewWithAccessibilityLabel:@"attachments"]];KIFTestStep *fillingInboxStep =[KIFTestStep stepToWaitForNotificationName:(NSString *)kOldMailBatchDelivered object:nil];[fillingInboxStep setTimeout:kSpecialTimeoutForLongTests];[步驟addObject:fillingInboxStep];返回步驟;}

<小時>

KIF 2.0 示例代碼:KIF 2.0 使用 Xcode 5 的全新 test navigator.. 這是一個巨大 比 KIF 1.0 所做的改進.. 現在您的測試感覺比過去更加有機和自然..(即它是實時進行的..而不是創建在未來運行的場景等)..你甚至可以用播放按鈕等來測試每個..你應該試試看.

這里有一些例子(同樣使用 gherkin 語法):

#import <KIF/KIF.h>#import "KIFUITestActor+EXAdditions.h"#import "KIFUITestActor+UserRegistration.h"@interface 登錄測試:KIFTestCase@結尾@implementation 登錄測試- (void)testReset {[測試儀flushDbase];[測試儀重置];}/* @假設應用程序處于全新的干凈狀態@and 沒有人在服務器上注冊過@then 用戶可以在服務器上注冊他們自己@and 立即從騎手的地圖開始@and 他們在地圖上的位置顯示*/- (void)testRegistration{[測試儀flushDbase];[測試儀重置];[測試者單用戶注冊];[測試人員 showUserCurrentLocationOnMap];}/* @假設用戶已經注冊到服務器@and 用戶當前沒有登錄@then 用戶可以使用他們的用戶名和密碼登錄@and 立即從騎手的地圖開始@and 他們在地圖上的位置顯示*/- (void)testSuccessfulLogin{[測試儀重置];[測試人員登錄];[測試人員 showUserCurrentLocationOnMap];}/* @假設用戶已經注冊@并且用戶在應用程序啟動之前已經登錄@then 用戶從地圖視圖開始,位置可見@and 按鈕提示他們設置接送地點*/- (void)testStartOfApplication {[測試人員 showUserCurrentLocationOnMap];[測試儀顯示PickUpButton];}@結尾

下面是分類文件中一些測試用例的實現:

- (void)reset{[自我運行塊:^KIFTestStepResult(NSError **錯誤){BOOL 成功重置 = YES;//為您的應用程序執行實際重置.如果失敗,則設置successfulReset = NO.AppDelegate* appDelegate = [[UIApplication sharedApplication] 委托];[appDelegate resetApp];KIFTestCondition(successfulReset, error, @"未能重置應用程序的某些部分.");返回 KIFTestStepResultSuccess;}];}- (void)flushDbase {[自我運行塊:^KIFTestStepResult(NSError **錯誤){NSURL *url = [NSURL URLWithString:@"http://randomdomain.com/flush_db"];NSURLRequest *request = [NSURLRequest requestWithURL:url];NSError *connectionError = nil;BOOL databaseFlushSucceeded = YES;NSURLResponse *響應;NSData *resultData = [NSURLConnection sendSynchronousRequest:request returnedResponse:&response error:&connectionError];如果(!結果數據){databaseFlushSucceeded = 否;KIFTestCondition(databaseFlushSucceeded, error, @"連接服務器失敗!");}如果(連接錯誤){databaseFlushSucceeded = 否;KIFTestCondition(databaseFlushSucceeded, error, [NSString stringWithFormat:@"連接失敗.錯誤: %@", [connectionError localDescription]]);}返回 KIFTestStepResultSuccess;}];}- (void)navigateToLoginPage{[self tapViewWithAccessibilityLabel:@"登錄郵箱"];}- (void)returnToLoggedOutHomeScreen{[self tapViewWithAccessibilityLabel:@"Logout"];[self tapViewWithAccessibilityLabel:@"Logout"];//關閉警報.}

Note: I added kif to the title just for search indexing puposes, considering that most of the answer turned out to discuss it

I'm looking for something like selenium for iOS, basically a test-automation/unit test framework that can run a certain UI scenario many many times until it crashes, which would help me narrow down the cause of a UI bug that happens very rarely and randomly.

(and by the way, I've NSLogged every single line of code of datasource/table interaction and spent hours analyzing the potential cause.. but found nothing conclusive.. again this bug very rarely happens).

I looked at some of the unit testing frameworks in iOS, but they seem to be so many. I'm not sure which to pick. Also my reference to selenium is based on conjecture, as I've worked with QA folks who've used Selenium in large web projects in the past (and i'm assuming that there must be something similar for iOS).

Now that I'm a one man team working on an iOS project, I'm gonna have to put a QA hat on and figure this bug out.

I'm facing a classic bug that happens when there is a discrepancy between the actual number of rows inserted in a UITableView and the number of rows that the datasource delegate returns. This is the error message:

*** Assertion failure in -[UITableView
 _endCellAnimationsWithContext:] Exception in insertRows: Invalid
 update: invalid number of rows in section 0.

The number of rows contained in an existing section after the update (2) must be equal to
 the number of rows contained in that section before the update (2),
 plus or minus the number of rows inserted or deleted from that section
 (1 inserted, 0 deleted) and plus or minus the number of rows moved
 into or out of that section (0 moved in, 0 moved out).

I click on a UITableViewCell that takes me into another UITableView. Sometimes it works

and sometimes (very rarely) it doesn't (with the above error):

解決方案

update:.. i've added example code about KIF 2.0 at the bottom after divider.. for those who are more interested in KIF than the specific problem i'm facing:

After some research and experimenting.. I've narrowed down my options to two test-automation libraries: Frank and KIF. I ultimately decided to use KIF while borrowing cucumber's Gherkin syntax to describe my unit tests.

The reason I chose KIF (rather than Frank) was that KIF is 100% obj-c based, rather than using ruby as well as was the case with Frank. So setting up is simpler, and it was more applicable to my narrow test case requirement. That being said, I admit Frank would be more useful if my application was more complicated (ie using intput from multiple servers etc). You can see the last quarter of this excellent presentation to learn more about the pros and cons of KIF, Frank and other automation-testing frameworks including Apple's own UI Automation.

After using KIF, I found the bug causing the error above, and I could reproduce it using KIF 100% of the time! The reason why it happened so rarely was because it happened only when I tapped through the screens really fast.. and since KIF automates the steps.. it does them at an incredibly fast speed.. which exposed the bug :).

So following will be a sample of the code I used for testing.. this is just to give you a quick feel of what KIF (and Gherkin) can do for you:

in one file I specify the scenarios I want to run:

- (void)initializeScenarios;
{
    [self addScenario:[KIFTestScenario scenarioToCompleteSignInAndLoadInbox]];
    [self addScenario:[KIFTestScenario scenarioToFillAttachmentsWithData]];
    [self addScenario:[KIFTestScenario scenarioToViewAndLoadFileBucket]];
    [self addScenario:[KIFTestScenario scenarioToViewAndLoadFileBucketSubView]];
}

each scenario maps to steps (to understand more about the gherkin syntax -and behavioral driven development, which is based on test driver development, I strongly recommend to read this excellent book about cucumber):

/* @given the application is at a fresh state
   @and   the user already has an imap email account with a valid username/pwd

   @then  the user can successfully log in
   @and   the inbox view will be loaded
   @and   the inbox will get loaded with the latest batch of emails in the user inbox
 */
+ (id)scenarioToCompleteSignInAndLoadInbox
{
    KIFTestScenario *scenario = 
      [KIFTestScenario scenarioWithDescription:@"Test that a user 
                                                 can successfully log in."];
    [scenario addStepsFromArray:[KIFTestStep stepsCompleteSignInAndLoadInbox]];

    return scenario;
}


/* @given that the user is already signed in
   @and   the user has already downloaded their folders 

   @then  the user can click on the folders view
   @and   the user can click on the 'attachments' remote folder
   @and   the latest batch from the 'attachments' remote folder will download
 */
+ (id)scenarioToFillAttachmentsWithData {
    KIFTestScenario* scenario = 
      [KIFTestScenario scenarioWithDescription:@"Test that we can view the 
                                                 attachments folder and fill 
                                                 it with data."];
    [scenario addStepsFromArray:[KIFTestStep stepsToFillAttachmentsWithData]];
    return scenario;

}

/* @given that the user is already signed in
   @and   the user has already downloaded their folders
   @and   the user has already downloaded attachments

   @then  the user can click on inbox menu button
   @and   the user can click on folder list menu button
   @and   the user can click on the file bucket icon (on the account list view)
   @and   the data for the file bucket is fetched from the dbase
   @and   the file bucket view displayes the attachments
 */
+ (id)scenarioToViewAndLoadFileBucket {
    KIFTestScenario *scenario = 
       [KIFTestScenario scenarioWithDescription:@"Test that a user can successfully 
                                                  view and load 
                                                  file bucket parent view"];
    [scenario addStepsFromArray:[KIFTestStep stepsToViewAndLoadFileBucketPage]];

    return scenario;
}

/* @given that the user is already signed in
   @and   the user has already downloaded their folders
   @and   the user has already downloaded attachments
   @and   the user has already opened file bucket view 

   @then  the user can click on a random row in the file bucket view table
   @and   the subview will retrieve data from the dbase pertaining to that row
   @and   the subview will display the data in the uitableview
 */
+ (id)scenarioToViewAndLoadFileBucketSubView {
    KIFTestScenario *scenario = 
       [KIFTestScenario scenarioWithDescription:@"Test that a user can successfully
                                                  view and load filet
                                                  bucket sub view"];
    [scenario addStepsFromArray:[KIFTestStep stepsToViewAndLoadFileBucketSubPage]];
    return scenario;   
}

and steps are defined using KIF's UI automation methods (this is just one example):

// this step assumes there is an attachment folder that contains emails with attachments
+ (NSArray *)stepsToFillAttachmentsWithData {

    NSMutableArray* steps = [@[] mutableCopy];

    [steps addObject:
        [KIFTestStep stepToTapViewWithAccessibilityLabel:@"InboxMenuButton"]];

    NSIndexPath* indexPath = 
        [NSIndexPath indexPathForRow:remoteAttachmentFolderNumber inSection:0];
    KIFTestStep* tapAttachmentRowStep = 
        [KIFTestStep stepToTapRowInTableViewWithAccessibilityLabel:
                                     @"attachments" atIndexPath:indexPath];

    [steps addObject:[KIFTestStep stepToWaitForNotificationName:
         (NSString *)kBeganSyncingOlderEmails object:nil           
                          whileExecutingStep:tapAttachmentRowStep]];

    [steps addObject:tapAttachmentRowStep];

    [steps addObject:
        [KIFTestStep stepToWaitForViewWithAccessibilityLabel:@"attachments"]];

    KIFTestStep *fillingInboxStep = 
        [KIFTestStep stepToWaitForNotificationName:
                                 (NSString *)kOldMailBatchDelivered object:nil];

    [fillingInboxStep setTimeout:kSpecialTimeoutForLongTests];
    [steps addObject:fillingInboxStep];

    return steps;
}


KIF 2.0 sample code: KIF 2.0 uses Xcode 5's all new test navigator.. which is a huge improvement than what KIF 1.0 was doing.. now your tests feel a lot more organic and natural than the past.. (ie it goes in real time.. rather than creating scenarios that run in the future etc).. you even get to test each one with a play button etc.. you should try it out.

here are some examples (again using gherkin syntax):

#import <KIF/KIF.h>
#import "KIFUITestActor+EXAdditions.h"
#import "KIFUITestActor+UserRegistration.h"

@interface LoginTests : KIFTestCase

@end
@implementation LoginTests

- (void)testReset {
    [tester flushDbase];
    [tester reset];
}

/* @given that the app is in a fresh clean state
 @and   that no one has ever registered with the server

 @then  the user can register their themselves with the server
 @and   immediately start with the rider's map
 @and   their location on the map shows
 */

- (void)testRegistration
{
    [tester flushDbase];
    [tester reset];
    [tester singleUserRegistration];
    [tester showUserCurrentLocationOnMap];
}

/* @given that the user has already registered with the server
   @and the user is not currently logged in

 @then  the user can login using their user name and password
 @and   immediately start with the rider's map
 @and   their location on the map shows
 */
- (void)testSuccessfulLogin
{
    [tester reset];
    [tester login];
    [tester showUserCurrentLocationOnMap];
}

/* @given that the user has already registered 
   @and that the user is already logged in before app launch

 @then the user starts on the map view with the location visible
 @and the button prompts them to set pick up location
 */
- (void)testStartOfApplication {
    [tester showUserCurrentLocationOnMap];
    [tester showsPickUpButton];
}
@end

here is the implementation of some of the test cases in the category files:

- (void)reset
{
    [self runBlock:^KIFTestStepResult(NSError **error) {
        BOOL successfulReset = YES;

        // Do the actual reset for your app. Set successfulReset = NO if it fails.
        AppDelegate* appDelegate = [[UIApplication sharedApplication] delegate];
        [appDelegate resetApp];

        KIFTestCondition(successfulReset, error, @"Failed to reset some part of the application.");

        return KIFTestStepResultSuccess;
    }];
}

- (void)flushDbase {
    [self runBlock:^KIFTestStepResult(NSError **error){
        NSURL *url = [NSURL URLWithString:@"http://randomdomain.com/flush_db"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSError *connectionError = nil;

        BOOL databaseFlushSucceeded = YES;

        NSURLResponse *response;
        NSData *resultData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&connectionError];
        if (!resultData) {
            databaseFlushSucceeded = NO;
            KIFTestCondition(databaseFlushSucceeded, error, @"failed to connect to server!");
        }

        if (connectionError) {
            databaseFlushSucceeded = NO;
            KIFTestCondition(databaseFlushSucceeded, error, [NSString stringWithFormat:@"connection failed. Error: %@", [connectionError localizedDescription]]);
        }

        return KIFTestStepResultSuccess;
    }];
}


- (void)navigateToLoginPage
{
    [self tapViewWithAccessibilityLabel:@"login email"];
}

- (void)returnToLoggedOutHomeScreen
{
    [self tapViewWithAccessibilityLabel:@"Logout"];
    [self tapViewWithAccessibilityLabel:@"Logout"]; // Dismiss alert.
}

這篇關于KIF:如何自動運行/壓力測試 iOS 應用程序以找出罕見 UI 錯誤的原因?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Using Instruments to test an iOS app without having source code to the application(在沒有應用程序源代碼的情況下使用 Instruments 測試 iOS 應用程序)
How to provide login credentials to an automated android test?(如何為自動化的 android 測試提供登錄憑據?)
Android Test Automation tools(Android 測試自動化工具)
How to fix error quot;Could not detect Mac OS X Version from sw_vers output: #39;10.12 #39;quot; from Appium(如何修復錯誤“無法從 sw_vers 輸出檢測 Mac OS X 版本:10.12來自Appium)
How do you test an Android application across multiple Activities?(如何跨多個活動測試 Android 應用程序?)
UITableView: Handle cell selection in a mixed cell table view static and dynamic cells(UITableView:在混合單元格表視圖靜態和動態單元格中處理單元格選擇)
主站蜘蛛池模板: 可以在线观看av的网站 | 日韩精品在线观看一区二区 | 国产成人精品一区二区三 | 国产传媒在线观看 | 国产精品国产精品国产专区不卡 | 久久久久一区二区 | 视频一区二区三区四区五区 | 国产精品久久久久久久久久三级 | 天天射网站| 久久国产精品久久久久久 | 夜夜操天天艹 | 日韩欧美在线播放 | 夜夜操天天干 | 久久国产精品久久久久久 | 欧美精品在线免费观看 | 日韩精品一区二区三区在线播放 | 在线成人 | 日韩中文字幕一区 | 99免费精品视频 | 亚洲一区二区精品视频 | 99色视频| 国产精品美女久久久久久久久久久 | 亚洲一区中文字幕在线观看 | 韩国av网站在线观看 | 午夜天堂精品久久久久 | 一级aaaaaa毛片免费同男同女 | 久久精品国产一区 | 久优草 | 精品视频 免费 | 国产综合久久 | 91视频一88av| 国产精品日韩 | 久久午夜剧场 | 二区在线视频 | 日本精品视频在线观看 | 国产高清一二三区 | 一级欧美一级日韩片免费观看 | 色狠狠桃花综合 | 亚洲精品99 | 国产成人免费视频网站视频社区 | 午夜影晥 |