iOS-SwiftMonkey測試

Android中的Monkey測試極大的幫助Android開發(fā)者保證了開發(fā)質(zhì)量,iOS自身是沒有Monkey測試的,最開始有基于UIAutomation 的 monkey 測試[https://github.com/jonathanpenn/ui-auto-monkey]. xCode7之后,UIAutomation被棄用,對應(yīng)Monkey也隨之淡化.當(dāng)大家習(xí)慣Monkey測試,突然消失之后就會懷念,正所謂有需求就會有市場,老外用Swift基于XCUITesting框架開發(fā)新的Monkey工具SwiftMonkey.

Swift Monkey測試

SwiftMonkey基于Swift語言編寫,按照SwiftMonkey提供的Demo,運行之后看到效果如下圖所示:


SwiftMonkey.gif

SwiftMonkey實現(xiàn)測試需要SwiftMonkey和SwiftMonkeyPaws兩個框架,如果我們的項目開始就是Swift語言編寫的,那么使用起來就非常簡單,主要過程如下:
①將Demo中SwiftMonkey和SwiftMonkeyPaws兩個項目拖入自身的Swift項目中.

FlyElephant.png

②SwiftMonkey作為FrameWork加入UITest對應(yīng)的Target文件中:


FlyElephant.png

③SwiftMonkeyPaws作為FrameWork加入App項目對應(yīng)的Target中;


FlyElephant.png

④AppDelegate中加入Paws:

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    var paws: MonkeyPaws?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        paws = MonkeyPaws(view: window!)
        return true
    }

⑤UITest中加入Monkey測試代碼:

override func setUp() {
        super.setUp()
        
        // Put setup code here. This method is called before the invocation of each test method in the class.
        
        // In UI tests it is usually best to stop immediately when a failure occurs.
        continueAfterFailure = false
        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
        XCUIApplication().launch()

        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
    }
    
    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of each test method in the class.
        super.tearDown()
    }
    
    func testMonkey() {
        let application = XCUIApplication()
        
        // Workaround for bug in Xcode 7.3. Snapshots are not properly updated
        // when you initially call app.frame, resulting in a zero-sized rect.
        // Doing a random query seems to update everything properly.
        // TODO: Remove this when the Xcode bug is fixed!
        _ = application.descendants(matching: .any).element(boundBy: 0).frame
        
        // Initialise the monkey tester with the current device
        // frame. Giving an explicit seed will make it generate
        // the same sequence of events on each run, and leaving it
        // out will generate a new sequence on each run.
        //let monkey = Monkey(frame: application.frame)
        let monkey = Monkey(seed: 123, frame: application.frame)
        
        // Add actions for the monkey to perform. We just use a
        // default set of actions for this, which is usually enough.
        // Use either one of these but maybe not both.
        // XCTest private actions seem to work better at the moment.
        // UIAutomation actions seem to work only on the simulator.
        monkey.addDefaultXCTestPrivateActions()
        
        //monkey.addDefaultUIAutomationActions()
        
        // Occasionally, use the regular XCTest functionality
        // to check if an alert is shown, and click a random
        // button on it.
        monkey.addXCTestTapAlertAction(interval: 100, application: application)
        
        // Run the monkey test indefinitely.
        monkey.monkeyAround()
    }

這段代碼是SwiftMonkey的默認代碼,addDefaultXCTestPrivateActions是調(diào)用Apple私有手勢方法,addDefaultUIAutomationActions只在模擬器中有效,內(nèi)部實現(xiàn)如下:

 public func addDefaultXCTestPrivateActions() {
        addXCTestTapAction(weight: 25)
        addXCTestLongPressAction(weight: 1)
        addXCTestDragAction(weight: 1)
        addXCTestPinchCloseAction(weight: 1)
        addXCTestPinchOpenAction(weight: 1)
        addXCTestRotateAction(weight: 1)
        //addXCTestOrientationAction(weight: 1) // TODO: Investigate why this does not work.
    }

默認執(zhí)行點擊,長按,拖拽,捏合,旋轉(zhuǎn),橫豎屏切換操作,Weight代表的是時間間隔,如果覺得系統(tǒng)默認的操作過多,可以自行刪減.

monkeyAround代表次數(shù),默認如果不設(shè)置次數(shù),會一直執(zhí)行下去.

public func monkeyAround() {
        while true {
            actRandomly()
            actRegularly()
        }
    }
FlyElephant.gif

OC Monkey 測試

如果你的項目一開始就是Swift編寫,或者已經(jīng)全面遷移到Swift語言,恭喜你下面這段介紹可以忽略了.鑒于目前大部分App都是OC為主,如果直接按照Swift的套路去使用SwiftMonkey會遇到一些問題,有興趣可以自行實踐,以下是本人實戰(zhàn)過程.

① 將Demo中SwiftMonkey和SwiftMonkeyPaws兩個項目拖入自身的Swift項目中.

② 將Always Embed Swift Standard Libraries設(shè)置為YES.


Paste_Image.png

③ 正常的套路直接調(diào)用Moneky,MonkeyPaws類,但是事實上無法調(diào)用,折騰了很久,中間各種報錯.

④ 簡單粗暴的方式是將SwiftMonkey兩個項目中的Swift拷貝到OC項目中:


FlyElephant.png

⑤ AppDelegate中代碼實現(xiàn):

@interface AppDelegate ()

@property (strong, nonatomic) MonkeyPaws *paws;

@end

@implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    self.paws = [[MonkeyPaws alloc] initWithView:self.window tapUIApplication:true];

    return YES;
}

⑤ UITest測試代碼:

- (void)setUp {
    [super setUp];
    
    // Put setup code here. This method is called before the invocation of each test method in the class.
    
    // In UI tests it is usually best to stop immediately when a failure occurs.
    self.continueAfterFailure = NO;
    // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.
    [[[XCUIApplication alloc] init] launch];
    
    // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
}

- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testExample {
    // Use recording to get started writing UI tests.
    [XCUIDevice sharedDevice].orientation = UIDeviceOrientationPortrait;
    // Use XCTAssert and related functions to verify your tests produce the correct results.
}

- (void)testMonkey {
    
    XCUIApplication *application = [XCUIApplication new];
    CGRect frame = [[application descendantsMatchingType:XCUIElementTypeAny] elementBoundByIndex:0].frame;
    
    Monkey *monkey = [[Monkey alloc] initWithSeed:123 frame:application.frame];
    
    [monkey addDefaultXCTestPrivateActions];
    [monkey addXCTestTapAlertActionWithInterval:100 application:application];
    [monkey monkeyAround];
}
FlyElephant.gif

如果項目中之前沒有進行過Monkey測試,SwiftMonkey會幫我們測出一些以前開發(fā)中沒有注意的問題.SwiftMonkey涉及調(diào)用XCTesting的私有API,不建議包含SwiftMonkey直接上傳到AppStore.

參考資料
SwiftMonkey
SwiftMonkey :iOS 上的 monkey

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容