From 5d47ce8f2386e2d3217c92f5eac436d957554fe4 Mon Sep 17 00:00:00 2001 From: zhangbin Date: Mon, 14 Sep 2015 09:52:21 +0800 Subject: [PATCH] Add tools for converting the performance tests data to excel files. --- tests/performance-tests/Classes/Profile.cpp | 22 ++- tools/performance-analyze/README.md | 107 ++++++++++++++ tools/performance-analyze/convertor.py | 155 ++++++++++++++++++++ 3 files changed, 276 insertions(+), 8 deletions(-) create mode 100644 tools/performance-analyze/README.md create mode 100755 tools/performance-analyze/convertor.py diff --git a/tests/performance-tests/Classes/Profile.cpp b/tests/performance-tests/Classes/Profile.cpp index 65db95878c..1836cc44c4 100644 --- a/tests/performance-tests/Classes/Profile.cpp +++ b/tests/performance-tests/Classes/Profile.cpp @@ -6,7 +6,7 @@ #include "cocos2d.h" #include -#define LOG_FILE_NAME "PerformanceLog.json" +#define LOG_FILE_NAME_FMT "PerformanceLog-%s-%s.json" #define PLIST_FILE_NAME "PerformanceLog.plist" #define KEY_DEVICE "device" @@ -20,14 +20,14 @@ #define FILE_VERSION 1 -#define USE_PRETTY_OUTPUT_FORMAT 1 +#define USE_PRETTY_OUTPUT_FORMAT 0 #define USE_JSON_FORMAT 1 // For different device & os, change these values // TODO : get device info automatically -#define DEVICE_NAME "iphone 5s" -#define OS_VERSION "iOS 8.4" +#define DEVICE_NAME "DeviceName" +#define OS_VERSION "SystemVersion" static Profile* s_profile = nullptr; @@ -223,10 +223,13 @@ void Profile::flush() testData[KEY_TIMESTAMP] = Value(genStr("%ld", t)); #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID - std::string checkPath = "/mnt/sdcard"; + std::string checkPath = "/mnt/sdcard/PerfTest"; auto writablePath = checkPath; if (! cocos2d::FileUtils::getInstance()->isDirectoryExist(checkPath)) { - writablePath = cocos2d::FileUtils::getInstance()->getWritablePath(); + auto createRet = cocos2d::FileUtils::getInstance()->createDirectory(checkPath); + if (! createRet) { + writablePath = cocos2d::FileUtils::getInstance()->getWritablePath(); + } } cocos2d::log("write path : %s", writablePath.c_str()); #else @@ -234,8 +237,11 @@ void Profile::flush() #endif #if USE_JSON_FORMAT - std::string fullPath = genStr("%s/%s", writablePath.c_str(), LOG_FILE_NAME); - + char timeStr[64]; + strftime(timeStr, sizeof(timeStr), "%Y-%m-%d-%H%M", localtime(&t)); + std::string fileName = genStr(LOG_FILE_NAME_FMT, DEVICE_NAME, timeStr); + std::string fullPath = genStr("%s/%s", writablePath.c_str(), fileName.c_str()); + rapidjson::Document document; rapidjson::Document::AllocatorType& allocator = document.GetAllocator(); rapidjson::Value theData = valueMapToJson(testData, allocator); diff --git a/tools/performance-analyze/README.md b/tools/performance-analyze/README.md new file mode 100644 index 0000000000..7bf235c11b --- /dev/null +++ b/tools/performance-analyze/README.md @@ -0,0 +1,107 @@ +# Performance Test Data Convertor + +## Overview + +Performance Test Data Convertor is used for converting the json files to excel files. The json files are generated from project `tests/performance-tests`. + +## Requirement + +* Python 2.7 is required. (Python 2.7.5 is well tested) +* [xlwt](https://pypi.python.org/pypi/xlwt/) for python to write excel files. + +## Generate test data + +1. Change the device name in the tests source code. +Now you should modify the device name in `tests/performance-tests/Classes/Profile.cpp` before running the tests. Sample code: + + ``` + // For different device & os, change these values + // TODO : get device info automatically + #define DEVICE_NAME "TheDeviceName" + #define OS_VERSION "SystemVersion" + ``` + +2. Run the performance-tests project on devices. +Once the project started, you will see a scene like this: +![test-scene][test-scene.jpg] + +3. Click the menu `Start AutoTest`. Then the performance tests will running automatically. Once the scene stopped at the scene again. It's mean the autotesting is end. + +## Get the generated json files + +After the test data generated, you can get the json file from the device. +The json file will be named with format : `PerformanceLog-[DEVICE_NAME]-[TIMESTAMP].json`. + +For different OS, you can get the json files by different steps: + +### From iOS devices + +The json files will generated in the `Document` folder of the app. So you can get the json files by iTunes by steps: +![itunes][itunes.jpg] + +### From Android devices + +The json files will be generated in the path `/mnt/sdcard/PerfTest`. So you can get the json files by commands like this: + +* Windows System + + Run the command in cmd: + ``` + %ANDROID_SDK_ROOT%\platform-tools\adb pull /mnt/sdcard/PerfTest C:\Users\USER_NAME\MY_LOG_FOLDER + ``` + +* Mac System + + Run the command in terminal: + ``` + $ANDROID_SDK_ROOT/platform-tools/adb pull /mnt/sdcard/PerfTest ~/MY_LOG_FOLDER + ``` + +### From Mac devices + +The json files will be generated in the path `~/Document`. + +### From Win32 devices + +The json files will be generated in the AppData path. For different system versions, it will be different path. +The path will be `C:\Users\USER_NAME\AppData\Local\performance-tests` on Win8.1. + +## Convert json files to excel files + +When the json files are ready, you can convert the json files to excel files by `tools/performance-analyze/convertor.py`. +The usage of the tool: + +``` +usage: convertor.py [-h] -s SRC_PATH [-o OUTPUT_PATH] + +Performance test data convertor. + +optional arguments: + -h, --help show this help message and exit + -s SRC_PATH Specify the json file path or the folder path of json files. + -o OUTPUT_PATH Specify the output path of excel files. +``` + +Tips: + +* The value of `-s` can be a json file or a folder which contains many json files. If it's a folder, then the json files in the folder will be converted to excel files one by one. + + +* You can specify the output path by `-o`. If it's not specified, the excel files will be placed in the same folder of json files. + + +* Each json file will generate an excel file. The excel file name will be same with the json file. For example: +`python convertor.py -s PerformanceLog-iphone4s-2015-09-11-1745.json` will generate a `PerformanceLog-iphone4s-2015-09-11-1745.xls` file. + + +* The format of the excel file will be looks like this: + + ![excel format][excel.jpg] + + 1. Each sheet shows the result of a test case. + 2. The cells with GREEN background color are the conditions of the test case. + 3. The cells with YELLOW background color are the result data of the test case. + +[test-scene.jpg]: http://i60.tinypic.com/ou86bs.jpg +[itunes.jpg]: http://i60.tinypic.com/33z4r53.jpg +[excel.jpg]: http://i57.tinypic.com/wvx500.jpg \ No newline at end of file diff --git a/tools/performance-analyze/convertor.py b/tools/performance-analyze/convertor.py new file mode 100755 index 0000000000..b2637fb1b0 --- /dev/null +++ b/tools/performance-analyze/convertor.py @@ -0,0 +1,155 @@ +#!/usr/bin/python +#-*- coding: UTF-8 -*- +# ---------------------------------------------------------------------------- +# Convert the performance test result from json files to excel. +# +# Author: Bill Zhang +# +# License: MIT +# ---------------------------------------------------------------------------- +''' +Convert the performance test result from json files to excel. +''' + +import xlwt +import os +import json + +from argparse import ArgumentParser + +DEFAULT_STYLE = 'borders: left thin, right thin, top thin, bottom thin;' +CONDITION_STYLE = 'pattern: pattern solid, fore_color light_green;' +RESULT_STYLE = 'pattern: pattern solid, fore_color light_yellow;' + +BASE_KEYS = [ + 'osVersion', + 'fileVersion', + 'timeStamp', + 'engineVersion', + 'device' +] + +KEY_CONDITION_HEADERS = "conditionHeaders" +KEY_RESULT_HEADERS = "resultHeaders" +KEY_RESULTS = "results" + +START_COL_INDEX = 0 +START_ROW_INDEX = 0 + +class KnownException(Exception): + pass + +class Convertor: + + def __init__(self, src_path, output_path=None): + self.src_path = self.change_to_abspath(src_path) + if not os.path.exists(self.src_path): + raise KnownException('%s is not existed!' % self.src_path) + + if output_path is None: + # not specified output path, default use source path + if os.path.isfile(self.src_path): + self.output_path = os.path.dirname(self.src_path) + else: + self.output_path = self.src_path + else: + self.output_path = self.change_to_abspath(output_path) + + def change_to_abspath(self, path): + ret = os.path.expanduser(path) + if not os.path.isabs(ret): + ret = os.path.abspath(ret) + + ret = os.path.normpath(ret) + return ret + + def get_col_width(self, col_str): + return 256 * (len(col_str) + 1) + + def convert_file(self, file_path): + f = open(file_path) + testData = json.load(f) + f.close() + + basename, ext = os.path.splitext(os.path.basename(file_path)) + dst_file_path = os.path.join(self.output_path, "%s.xls" % basename) + if os.path.isfile(dst_file_path): + os.remove(dst_file_path) + + workbook = xlwt.Workbook(encoding = 'ascii') + + default_style = xlwt.Style.easyxf(DEFAULT_STYLE) + con_style = xlwt.Style.easyxf("%s%s" % (DEFAULT_STYLE, CONDITION_STYLE)) + ret_style = xlwt.Style.easyxf("%s%s" % (DEFAULT_STYLE, RESULT_STYLE)) + + for key in testData.keys(): + if key in BASE_KEYS: + continue + + # create a sheet for the test case + sheetObj = workbook.add_sheet(key) + + # get test case data + caseInfo = testData[key] + + # Add headers for the test case + condHeaders = caseInfo[KEY_CONDITION_HEADERS] + retHeaders = caseInfo[KEY_RESULT_HEADERS] + curRow = START_ROW_INDEX + curCol = START_COL_INDEX + + col_widths = {} + for header in (condHeaders + retHeaders): + sheetObj.write(curRow, curCol, header, default_style) + col_width = self.get_col_width(header) + col_widths[curCol] = col_width + sheetObj.col(curCol).width = col_width + curCol += 1 + + rets = caseInfo[KEY_RESULTS] + for retInfo in rets: + curRow += 1 + curCol = START_COL_INDEX + for ret in retInfo: + if (curCol - START_COL_INDEX) < len(condHeaders): + use_style = con_style + else: + use_style = ret_style + sheetObj.write(curRow, curCol, ret, use_style) + new_width = self.get_col_width(ret) + old_width = col_widths[curCol] + if new_width > old_width: + sheetObj.col(curCol).width = new_width + col_widths[curCol] = new_width + curCol += 1 + + workbook.save(dst_file_path) + print("%s is generated." % dst_file_path) + + def do_convert(self): + if not os.path.exists(self.output_path): + os.makedirs(self.output_path) + + if os.path.isfile(self.src_path): + self.convert_file(self.src_path) + else: + for f in os.listdir(self.src_path): + full_path = os.path.join(self.src_path, f) + ignore, ext = os.path.splitext(f) + if os.path.isfile(full_path) and ext == '.json': + self.convert_file(full_path) + +if __name__ == '__main__': + parser = ArgumentParser(description="Performance test data convertor.") + parser.add_argument('-s', dest='src_path', required=True, help='Specify the json file path or the folder path of json files.') + parser.add_argument('-o', dest='output_path', help='Specify the output path of excel files.') + (args, unknown) = parser.parse_known_args() + + try: + convertor = Convertor(args.src_path, args.output_path) + convertor.do_convert() + except Exception as e: + if e.__class__.__name__ == "KnownException": + print(' '.join(e.args)) + else: + raise