1. Demand
Recent development reaction: Monkey / Auto traverses the FC, ANR and other problems during the test. It is impossible to accurately locate the cause and recurrence path of the problem through the log. It is hoped that the recording screen can be added during the test to facilitate the location of the path and cause of the problem recurrence. (for automatic traversal test, please refer to: https://github.com/bytedance/Fastbot_Android)
Defects of mobile phone's own recording screen:
- The duration cannot be controlled during the test
- It is easy to be interrupted in the test
- Long time screen recording consumes too much mobile phone memory
2. Solution ideas
Monkey / when traversing the test automatically, record the screen intermittently through the adb command, and then analyze the test log. If there is no error message, delete the previous record screen; otherwise, retain and export the record screen.
3. Flow chart
flow chart. jpg
4. Test process
4.1. Third party libraries required for Python environment and source code
4.2. Modify monkey as required_ through. Yaml configuration information (note the space between fields)
4.3. Turn on the log provided by the device and keep usb connected to the device. Do not interrupt during the test
4.4. Execute the main() method (in case of abnormality, the test will be automatically terminated and the screen recording will be exported to the script directory)
5. Yaml profile example
# Test type: Monkey/Through testType: Through # [Monkey] Monkey: # Package name packageName: com.google.android.dialer # Number of runs runTimes: 500 # Seed value runSeed: 999 # Event flow interval in milliseconds runThrottle: 500 pctTouch: 50 pctMotion: 20 pctTrackball: 5 pctSyskeys: 5 pctAppSwitch: 5 pctRotation: 5 # [automatic traversal] Through: # Package name packageName: com.example.anrfcapp # Test clock (unit: minutes) runMinutes: 10 # Time flow interval runThrottle: 500 # Screen recording configuration screenRecord: # Recording duration (in seconds) recordTime: 60
5. Source code
#!/usr/bin/python # -*- coding: utf-8 -*- # @Time : 2021/11/15 16:31 # @Author : CuiShuangqi # @Email : 1159533975@qq.com # @File : monkeyScreenRecord.py """ Requirements: Integration Monkey,Automatically traverse the test and add the screen recording function(Intermittent screen recording. If there is no error, the previous screen recording will be deleted) Note: please modify before testing monkey_through.yaml configuration file """ import os import time import yaml # Get mobile information def get_device_info(): # Waiting for phone connection print("Waiting for device connection...") os.system("adb wait-for-device") print("Device connected successfully,The parameters are as follows:") # Mobile phone model phoneModel = os.popen("adb shell getprop ro.product.model").read().strip('\n') # Mobile SOC socModel = os.popen("adb shell getprop ro.board.platform").read().strip('\n').upper() # Software version softwareVersion = os.popen("adb shell getprop ro.build.display.id").read().strip('\n') # Android version androidVersion = os.popen("adb shell getprop ro.build.version.release").read().strip('\n') print(f"[[mobile phone model]:{phoneModel}", f"\n[[mobile platform]:{socModel}", f"\n[[software version]:{softwareVersion}", f"\n[Android version]:{androidVersion}") # Read configuration information def read_yaml(test_type: str): yamlPath = os.path.join(os.getcwd(), "monkey_through.yaml") with open(yamlPath, "r", encoding="GBK") as f: return yaml.load(f.read(), Loader=yaml.FullLoader)[test_type] # Judge the mobile phone test environment def is_test_environment(test_type: str) -> bool: # Current directory of script curPath = os.getcwd() flag = False # Monkey test if test_type == "Monkey": print("Monkey There is no need to configure the test environment for testing!") flag = True # Automatic traversal test elif test_type == "Through": jarFiles = os.popen("adb shell find /sdcard/ -name '*.jar'").read() if "/sdcard/framework.jar" in jarFiles and "/sdcard/monkeyq.jar" in jarFiles: print("Already exists in the device framework.jar,monkeyq.jar!") flag = True else: cur_files = [] for root, dirs, files in os.walk(os.getcwd()): for f in files: cur_files.append(os.path.join(root, f)) frameworkJarPath = os.path.join(curPath, "framework.jar") monkeyqJarPath = os.path.join(curPath, "monkeyq.jar") # Judge whether there are jar packages in the script directory if frameworkJarPath in cur_files and monkeyqJarPath in cur_files: # There are jar packages in the current directory. Push the jar package to / sdcard/ if os.system(f"adb push {frameworkJarPath} /sdcard/") == 0 and \ os.system(f"adb push {monkeyqJarPath} /sdcard/") == 0: print("Push framework.jar,monkeyq.jar to/sdcard/Directory succeeded!") flag = True else: print("Push framework.jar,monkeyq.jar to/sdcard/Directory failed!") flag = False else: print("The current directory of the script does not exist framework.jar,monkeyq.jar!") flag = False else: print("Test type parameter error!") flag = False return flag def test_monkey_or_through(test_type: str): # Background operation if test_type == "Monkey": monkeyCommand = f'adb shell "monkey ' \ f'-p {read_yaml("Monkey")["packageName"]} ' \ f'--throttle {read_yaml("Monkey")["runThrottle"]} ' \ f'--randomize-throttle ' \ f'--ignore-crashes ' \ f'--ignore-timeouts ' \ f'--ignore-security-exceptions ' \ f'--ignore-native-crashes ' \ f'--pct-touch {read_yaml("Monkey")["pctTouch"]} ' \ f'--pct-motion {read_yaml("Monkey")["pctMotion"]} ' \ f'--pct-trackball {read_yaml("Monkey")["pctTrackball"]} ' \ f'--pct-syskeys {read_yaml("Monkey")["pctSyskeys"]} ' \ f'--pct-appswitch {read_yaml("Monkey")["pctAppSwitch"]} ' \ f'--pct-rotation {read_yaml("Monkey")["pctRotation"]} ' \ f'-v -v -v {read_yaml("Monkey")["runTimes"]} ' \ f'1>/sdcard/monkeyInfo.txt 2>/sdcard/monkeyError.txt &"' os.system(monkeyCommand) elif test_type == "Through": throughCommand = f'adb shell ' \ f'"CLASSPATH=/sdcard/monkeyq.jar:/sdcard/framework.jar ' \ f'exec app_process /system/bin com.android.commands.monkey.Monkey ' \ f'-p {read_yaml("Through")["packageName"]} ' \ f'--agent robot ' \ f'--running-minutes {read_yaml("Through")["runMinutes"]} ' \ f'--throttle {read_yaml("Through")["runThrottle"]} -v -v -v ' \ f'1>/sdcard/throughInfo.txt 2>/sdcard/throughError.txt &"' os.system(throughCommand) # Adobe Captivate def screen_record(test_type: str) -> str: # Recording seconds recordTime = read_yaml("screenRecord")["recordTime"] # Recording file name timeFlag = time.strftime('%Y-%m-%d_%H%M%S', time.localtime(time.time())) recordName = f"/sdcard/{test_type}_{timeFlag}.mp4" print("Recording screen...Do not disconnect!") recordCommand = f'adb shell screenrecord --time-limit {recordTime} {recordName}' os.system(recordCommand) print("Recording screen has ended!") # Returns the file name of the recorded mp4, so that the file can be deleted when there is no exception return recordName # Judge whether the mobile phone is abnormal def is_Exception(testType: str) -> bool: flag = False if testType == "Monkey": # Parse / sdcard / monkeyerror txt throughErrorInfo = os.popen('adb shell cat /sdcard/monkeyError.txt').read() if "ANR" in throughErrorInfo or "NOT RESPONDING" in throughErrorInfo or "CRASH" in throughErrorInfo: flag = True print("Monkey There are exceptions in the test!!!") elif testType == "Through": # Parse / sdcard / througherror txt throughErrorInfo = os.popen('adb shell cat /sdcard/throughError.txt').read() if "ANR" in throughErrorInfo or "NOT RESPONDING" in throughErrorInfo or "CRASH" in throughErrorInfo: flag = True print("There is an exception in automatic traversal!!!") # Export video else: print("No abnormality found in this test!") return flag # main def main(): get_device_info() testType = read_yaml("testType") if is_test_environment(testType): # Start testing test_monkey_or_through(testType) while True: # Recording screen recordName = screen_record(testType) findMonkeyPsCommand = 'adb shell ps | findstr -i "monkey"' commandList = os.popen(findMonkeyPsCommand).read().strip("\n").split(" ") if commandList[0] != "": # Judge whether there is any abnormality if is_Exception(testType): # Export screen recording to current directory if os.system(f"adb pull {recordName} {os.getcwd()}") == 0: print(f"Video exported to:[{os.getcwd()}]") else: print(f"Failed to export video, saved:{recordName}") # Query the result of monkey process id and empty it myList = [i for i in commandList if i != ''] # The second value in the list is the monkey process id monkeyId = myList[1] # kill the traversal process if os.system(f"adb shell kill {monkeyId}") == 0: print("Process ended successfully!") else: print("Process end failed,Please try to end the process manually!") break else: # Delete the previous screen recording and record it again if os.system(f"adb shell rm {recordName}") == 0: print("Screen recording deleted successfully!") else: print("Failed to delete screen recording!") break else: # The test has ended print("The test has ended,No abnormality found, the last screen recording of the test has been saved!") break else: print("Failed to initialize test environment!") if __name__ == '__main__': main()
The following is the supporting materials. For friends who do [software testing], it should be the most comprehensive and complete war preparation warehouse. This warehouse has also accompanied me through the most difficult journey. I hope it can also help you!
Finally, it can be in the official account: programmer Hao! Get a 216 page interview document of Software Test Engineer for free. And the corresponding video learning tutorials for free!, It includes basic knowledge, Linux essentials, Shell, Internet program principles, Mysql database, special topics of packet capture tools, interface test tools, test advanced Python programming, Web automation test, APP automation test, interface automation test, advanced continuous integration of test, test architecture, development test framework, performance test, security test, etc.
If my blog is helpful to you and you like my blog content, please click "like", "comment" and "collect" for three times! Friends who like software testing can join our testing technology exchange group: 779450660 (there are various software testing resources and technical discussions)