swiftmonkey secondary source analysis and development of ideas

swift monkey monkey is used for testing iOS side, swift written language, based on XCTest testing framework, call the private API  XCEventGenerator , continue to generate event event, but more than Xcode10.1 XCTestFramework has been removed this API, so if you want to in the words used above 10.1 need for secondary development.
 
When using monkey Android end of the discovered different app demand for monkey tests are different, the basic need for tools framework native secondary development to meet different testing needs, Android, then fastmonkey meet the basic needs of some customization scenarios , but iOS is not enough here, so we see the next swiftmonkey source, according to their own needs secondary development.
 
The use of specific steps not to go into details, there are many online resources, it recorded a github address bar
 
In fact, I find this tool also has not been updated for some time.
 
Constitute a framework


Brief files constitute the entire tool.
 
Monkey : program entry is mainly configured monkey, monkey and the like run
 
MonkeyXCTest : see the comment, then expand monkey was supposed to use a common XCTest API to generate events, but did not write. . .
 
MonkeyXCTestPrivate : this is the use of proprietary API to generate code for various events
 
MonkeyUIAutomation : this is the use of UIautomation framework to perform a variety of events, but only supports simulator
 
The Random : this is a function of various random number generation
 
 
The main part of the source code analysis

 
monkeyAround perform a method (according to the number of executions, execution time), random events generated by the circulation
 
 publicfuncmonkeyAround(iterations: Int) {
        for_in1... iterations {
            actRandomly()
            actRegularly()
        }
    }

 
actRandomly () is a random event to add execution
actRegular () is executed at regular intervals incident
 
 
/// Generate one random event.
    publicfuncactRandomly() {
        letx = r.randomDouble() * totalWeight
        foraction inrandomActions{
            ifx < action.accumulatedWeight {
                action.action()
                return
            }
        }
    }
 
    /// Generate any pending fixed-interval events.
    publicfuncactRegularly() {
        actionCounter+= 1
 
        foraction inregularActions{
            ifactionCounter% action.interval == 0{
                action.action()
            }
        }
    }

 

 
You can see be removed from the random array of random events and then perform the action, add an event when the need to add an event proportion, the proportion will go to perform according to the event when the event execution.
 
So where events are randomly generated from it?
 
When using monkey, you need to add a random event.
E.g:
monkey.addDefaultXCTestPrivateActions()
 
Add default XCTest private events, view detailed method, you can see the proportion of random events added
 
publicfuncaddDefaultXCTestPrivateActions () {
        addXCTestTapAction(weight: 25)
        addXCTestLongPressAction(weight: 1)
        addXCTestDragAction(weight: 0)
        addXCTestPinchCloseAction(weight: 0)
        addXCTestPinchOpenAction(weight: 0)
        addXCTestRotateAction(weight: 0)
        //addXCTestOrientationAction(weight: 1) // TODO: Investigate why this does not work.
}
 
We can see it default to add a few event, and set the weight
Dir a look at that event, tapAction is how to add
 
In addXCTestTapAction method, the function to add a closure, the generated random Point, then call XCEventGenerator performed, no longer functions paste.
 
A point worth noting is, addXCTestTapAction addAction method is called to add an event to a random array and then iterate when executed
 
In addAction method there is a point which has a nested function is used to monitor the closure of the current application is always we want to test the app, if you find some systems because the call sign or events leading to exit the app, will again pull back.
 
funcactInForeground(_action: @escapingActionClosure) -> ActionClosure{
        return{
            guard#available(iOS9.0, *) else{
                action()
                return
            }
            letclosure: ActionClosure= {
                // state来判断当前app执行状态
                ifXCUIApplication().state!= .runningForeground{
                    XCUIApplication().activate()
                }
                action()
            }
            ifThread.isMainThread{
                closure()
            } else{
                DispatchQueue.main.async(execute: closure)
            }
        }
    }

 

 
At this point we can sort out the implementation process swiftmonkey
1. Initialization monkey
2. Add a random event, set the weight
3. Perform the monkey
 
Secondary development ideas
 
How secondary development?
 
To solve the problem swiftmonkey instrumented code to the app as an example.
 
The conventional method is to use the monkey to add to our own projects to execute, but when we understand its principles can transform a little lower.
 
swiftmonkey is based app, so first of all necessary to the project by the xcuiapplication lifted tests xcuitest performed, and then randomly executed. But if you understand, then you know XCTest XCTest support lifting the other app, as long as the incoming app bundleIdentifier can, so we can easily build a Xcode project and then import swiftmonkey files, create uitest file, but we need to specify before starting the monkey bundleid test the app on it.
 
E.g:
letapp2 = XCUIApplication(bundleIdentifier: "com.myapp.app")
app2.launch()
 
But after performing discovery or will pull back to this fake app was created, and why, when analyzing the source said that a point, at every execution of the event will determine what the current app (where the project monkey) whether to start active in the foreground, If not, it will pull up, so much the better judgment of the application we put into their actual app to be tested on it
 
E.g:
In actInForeground method, the application to change the actual test
 
It turned out to be:
if XCUIApplication().state!= .runningForeground{
       XCUIApplication().activate()
}

 

 
Read:
 
if XCUIApplication(bundleIdentifier: "com.myapp.app").state!= .runningForeground{
     XCUIApplication(bundleIdentifier: "com.myapp.app").activate()
}

 

 
So each will be tested to determine the actual app is running in the foreground, if not it will automatically pull up.
 
After transformation swiftmonkey above you do not need to insert the pile.
 
Another example is not supported Xcode10.1 above XCEventGenerator, that we can not replace this API, checked the information before there really is no better API can be used, if not replace the use of only 10.1 the previous XCTestFramework, but will XCTest update, better able to develop upwards rather than downwards compatible.
So I did a test, if you are using a public API does a lot slower.
 
For example to perform 50 times tapAction
Public API speed: about 14 seconds to about 3-4 per second action
Using private API speed: about 5 seconds, about 10 per second action
 
Speed ​​compared to the gap is still relatively large, but personally feel that if the test is app rather than a mobile phone testing, no need to over-pursue much stress tests, 3-4 per user action is beyond normal operating frequency of the app
 
By modifying addXCTestTapAction method
It turned out to be:
let semaphore = DispatchSemaphore(value: 0)
//            self!.sharedXCEventGenerator.tapAtTouchLocations(locations, numberOfTaps: numberOfTaps, orientation: orientationValue) {
//                semaphore.signal()
//            }
//            semaphore.wait()

 

 
Read:
 
if #available(iOS9.0, *) {
                letapp = XCUIApplication()
                letcoordinate = app.coordinate(withNormalizedOffset: CGVector(dx: locations[0].x/(app.frame.maxX/2), dy: locations[0].y/(app.frame.maxY/2)))
                coordinate.tap()
 
            } else{
                // Fallback on earlier versions
            }
 

 

 
Of course, more than just a simple idea and test changes, we may need to optimize the improvement according to the project.

 

Guess you like

Origin www.cnblogs.com/dreamyu/p/11280030.html