□ 1단계: 샘플 코드


아래의 코드를 실행하면 된다. 단, monkeyrunner의 버전이 최신 SDK가 아니라면 


나의 경우, 가장 오래된 SDK 버전도 가능 했다 (nexus one을 위한 버전)


MonkeyImage.loadFromFile에서 Error가 발생 한다.

AttributeError: type object 'com.android.monkeyrunner.MonkeyRunner' has no attribute 'loadImageFromFile'


현재 버전이 loadImageFromFile 히든 함수를 지원 하는지 알 수 있는 방법.

아래의 코드를 넣어서 실행 시켜 보면 알 수 있다.

for m in [MonkeyRunner, MonkeyDevice, MonkeyImage]:
       print "%s:\n    %s\n"%(m.__name__, dir(m))


#! /usr/bin/env monkeyrunner

import sys
import subprocess
from com.android.monkeyrunner
import MonkeyRunner, MonkeyDevice, MonkeyImage

TIMEOUT = 30
SERIALNO = 'emulator-5554'
REF = 'reference.png'
SCR = 'screenshot.png'
CMP = 'comparison.png'
ACCEPTANCE = 0.9

device = None


def testDropWidgetIntoFourthRow():
    reference = MonkeyImage.loadFromFile(REF)
    print "moving widget..."
    device.drag((230, 300), (230, 600), 2.0, 125)
    MonkeyRunner.sleep(3)
    screenshot = device.takeSnapshot()
    screenshot.writeToFile(SCR)
    if not screenshot.sameAs(reference, ACCEPTANCE):
       print "comparison failed, getting visual comparison..."
       subprocess.call(["/usr/bin/compare", REF, SCR, CMP])

def main():
    global device
    print "waiting for connection..."
    device = MonkeyRunner.waitForConnection(TIMEOUT, SERIALNO)
    if device:
       testDropWidgetIntoFourthRow()


if __name__ == '__main__':
     main()

위 코드는 Diego(테스팅 대가)가 monkeyImage에 loadFromFile이라는 함수를 임의로 추가해서 사용한 코드이다.

따라서 monkeyrunner 수정 없이는, 동작하지 않는 코드이다.



필자는 위코드를 아래와같이 변경해서 사용함.


#! /usr/bin/env monkeyrunner
import sys
import subprocess

from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice, MonkeyImage

TIMEOUT = 30
SERIALNO = 'emulator-5554'
REF = '../ImageStore/GameActivityDesire.png'
SCR = '../ImageStore/GameActivityGalaxyNexus_Resize.png'

CMP = 'comparison.png'
ACCEPTANCE = 0.9
device = None


def testDropWidgetIntoFourthRow():

#reference = MonkeyImage.loadFromFile(REF)
reference = MonkeyRunner.loadImageFromFile(REF)

#source = MonkeyImage.loadFromFile(SCR)
source = MonkeyRunner.loadImageFromFile(SCR)

if not source.sameAs(reference, ACCEPTANCE):
print "comparison failed, getting visual comparison..."
subprocess.call(["/usr/bin/compare", REF, SCR, CMP])



def main():
# for m in [MonkeyRunner, MonkeyDevice, MonkeyImage]:
# print "%s:\n %s\n"%(m.__name__, dir(m))
testDropWidgetIntoFourthRow()

if __name__ == '__main__':
main()



/*
이 코드의 특징은 takeSnapshot()의 사용없이, loadImageFromFile 함수만을 이용해서 기존에 저장된

이미지들간의 유사도를 sameAs 함수로 알아보는 것이다.

*/


Trouble shooting


리플랙트 에러가 발생하는 경우.

Monkeyrunner at java.lang.reflect.Method.invoke(Method.java:597)


해결방법

1) 비교할려는 두개의 이미지의 해상도가 같은지를 확인해라!

2) 이미지의 경로가 맞는지 확인해라! loadImageFromFile()함수는 경로가 틀려도 어떠한 에러도

발생 시키지 않는다.

3) monkeyrunner의 버전이 너무 낮은건 아닌지 확인 해라!




□ 2단계: 최신 monkeyrunner 구하기


정확히 릴리즈 몇부터 monkeyrunner의 히든 API로 loadFromFile이 존재하는지는 모르겠다.


분석에 사용된 Android version: AOSP-4.2_r2


디렉터리 위치: sdk/android/chimpchat/core/ChumpImageBase.java



공개된 API 리스트들이다.


MonkeyImage



string convertToBytes (string format)
Converts the current image to a particular format and returns it as a string that you can then access as an iterable of binary bytes.
tuple getRawPixel (integer x, integer y)
Returns the single pixel at the image location (x,y), as an a tuple of integer, in the form (a,r,g,b).
integer getRawPixelInt (integer x, integer y)
Returns the single pixel at the image location (x,y), as a 32-bit integer.
MonkeyImage getSubImage (tuple rect)
Creates a new MonkeyImage object from a rectangular selection of the current image.
boolean sameAs (MonkeyImage other, float percent)
Compares this MonkeyImage object to another and returns the result of the comparison. The percent argument specifies the percentage difference that is allowed for the two images to be "equal".
void writeToFile (string path, string format)
Writes the current image to the file specified by filename, in the format specified by format.



숨겨진 API


DictInit [MonkeyImage]
MonkeyImage [MonkeyImage]
getImpl [MonkeyImage]

convertToBytes [MonkeyImage]
writeToFile [MonkeyImage]
getRawPixel [MonkeyImage]
getRawPixelInt [MonkeyImage]
sameAs [MonkeyImage]
getSubImage [MonkeyImage]



□ 3단계: monkeyrunner를 수정해서 사용하기.


chimpchat 프로젝트에 생각보다 많은 좋은 API들이 있다. 하지만 이것을 사용 할 수 있는지는 연구를 해봐야한다. API가 어떤식으로 노출되어지는지 분석을 해봐야 할것 같다.





+ Recent posts