# -*- encoding=utf8 -*-
from common.cli.runner import AirtestCase, run_script
from argparse import *
import jinja2
import shutil
import os
import io
import time
import re
import report.report.report as report
import logging
from airtest.utils.logger import get_logger
from multiprocessing import Pool
import math
import requests
import json
import random
from common.confop import confOP


class CustomAirTestCase(AirtestCase):
    # @classMethod
    # def setUpClass(cls):
    #     super(CustomAirTestCase,cls).setUpClass()
    #
    # 类变量，多进程跑任务的时候用到
    summary_message = {}
    summary_message["caseNum"] = 0
    summary_message["passNum"] = 0
    summary_message['passRate'] = 0.0
    case_results = []
    log_list = []

    def __init__(self, work_space, case_path, log_path, runtime_log, log_level):
        """
        初始化一些环境变量
        :param work_space:
        :param case_path:
        :param log_path:
        :param runtime_log:
        """
        self.workspace = work_space
        self.case_path = case_path
        self.log_path = log_path
        self.runtime_log = runtime_log

        level = self.get_log_level(log_level)
        logger = get_logger("airtest")
        logger.setLevel(level)

    def get_phone_by_user(self, user):
        url = "http://cloud.baobaoshu.com/cloud/groupUser/findPhoneByUser?name=%s" % user
        payload = {}
        headers = {
            'Content-Type': 'application/json'
        }
        response = requests.request("GET", url, headers=headers, data=payload)
        result = json.loads(response.text)
        return result["data"]

    def dingding_send_markdown(self, env, title, content, job_url, author, token):
        at_phones = "@"
        at = {
                "atMobiles": [
                    # 需要填写自己的手机号，钉钉通过手机号@对应人
                ],
                "isAtAll": True  # 是否@所有人，默认否
            }
        if author in ["zhangaizhen", "caiyubing", "hongli", "lihong", "wuchenlong"]:
            at_phones = "@ALL"
        else:
            phones = self.get_phone_by_user(author)
            if phones.isdigit():
                at_phones = at_phones + phones
                at["isAtAll"] = False
            else:
                at_phones = "@ALL"
                at["isAtAll"] = True
            phoneArr = []
            phoneArr.append(str(phones))
            at["atMobiles"] = phoneArr

        """
        报错的用例以markdown的格式发钉钉群
        :param title: 消息主题
        :param content: 消息内容
        :return:
        """
        url = 'https://oapi.dingtalk.com/robot/send?access_token=%s' % token
        pagrem = {
            "msgtype": "markdown",
            "markdown": {
                "title": "自动化执行结果",
                "text": "#### **[" + str(env) + "环境]" + str(title) + " 用例报错** \n> ##### 执行链接: " + str(
                    job_url) + "\n> ##### 接口返回值: " + str(content) + " " + str(at_phones)
            },
            "at": at
        }
        headers = {
            'Content-Type': 'application/json'
        }
        response = requests.post(url, data=json.dumps(pagrem), headers=headers)
        return response.text

    def get_error_log_info(self, log):
        """
        获取报错的日志
        :param log:
        :return:
        """
        txt_log = os.path.join(log, 'log.txt')
        f = open(txt_log, 'r', encoding='utf-8')
        lines = f.readlines()
        f.close()
        for line in lines:
            if "assert_not_equal" in line:
                expect_val = json.loads(line)["data"]["call_args"]["first"]
                return expect_val
            else:
                return ""

    def get_log_level(self, log_level):
        if log_level == 'warn':
            return logging.WARN
        elif log_level == 'debug':
            return logging.DEBUG
        elif log_level == 'info':
            return logging.INFO
        else:
            print("输入日志信息不对")
            return logging.DEBUG

    def setUp(self):
        print("custom setup")
        super(CustomAirTestCase, self).setUp()

    def tearDown(self):
        print("custom tearDown")
        super(CustomAirTestCase, self).tearDown()

    def get_author(self, case_name, filepath):
        """
        获取case是谁写的
        :return:
        """
        name = 'Unknown'
        pyfile = open(filepath + os.sep + case_name + '.air' + os.sep + case_name + '.py', 'r', encoding='utf-8')
        lines = pyfile.readlines()
        for line in lines:
            line = line.replace(" ", "")
            if '__author__' in line:
                line = line.split('__author__=')[-1]
                name = line.replace('"', '')
                name = name.strip().strip('\n')
        pyfile.close()
        return name

    def create_log(self, log_path, air_name):
        """
        创建对应case的log 文件
        :return:
        """
        if os.path.isdir(log_path):
            pass
        else:
            os.makedirs(log_path)
        log = os.path.join(log_path, air_name)
        if os.path.isdir(log):
            shutil.rmtree(log)
        else:
            os.makedirs(log)
        return log

    def get_case_runtime(self, log):
        """
        读取case运行日志，获取case执行开始时间，结束时间
        :param log:
        :return:
        """
        txt_log = os.path.join(log, 'log.txt')
        f = open(txt_log, 'r', encoding='utf-8')
        lines = f.readlines()

        f.close()
        start_time = float(re.findall('.*"start_time": (.*), "ret".*', lines[0])[0])
        start_time = int(start_time * 1000)
        try:
            end_time = float(re.findall('.*"end_time": (.*)}}.*', lines[-1])[0])
        except:
            # case执行失败的话没打end_time
            end_time = float(re.findall('.*"time": (.*), "data".*', lines[-2])[0])
        end_time = int(end_time * 1000)
        return start_time, end_time

    def assign_tasks(self, task_list, num):
        """
        将任务平均分配给num个设备跑
        :param task_list: 待分配任务列表
        :param num: num个设备
        :return:
        """
        all_list = []
        length = len(task_list)
        for i in range(num):
            one_list = task_list[math.floor(i / num * length):math.floor((i + 1) / num * length)]
            all_list.append(one_list)
        return all_list

    def get_device(self, case_dict, script):
        """
        根据之间跑case时候记录的设备对应执行的case，获取某个脚本是在哪个设备上执行的
        :param case_dict:
        :param script:
        :return: devie
        """
        for k in case_dict:
            if script in case_dict[k]:
                return k

    def get_cases_and_log(self, case_name, device_list):
        """
        :return: 获得需要执行的所有air的文件夹，同时对每个设备创建log目录
        """
        dirs_ls = []
        for dirs in os.listdir(self.case_path):
            isdir = os.path.join(self.case_path, dirs)
            if os.path.isdir(isdir) and isdir.endswith(".air"):
                air_name = dirs.replace('.air', '')
                if case_name == 'all' or air_name in case_name:
                    script = os.path.join(self.case_path, isdir)
                    dirs_ls.append(script)
                    for device in device_list:
                        self.create_log(os.path.join(self.log_path, device), air_name)
        return dirs_ls

    def get_all_dir(self, case_name):
        """
        :return: 获得需要执行的所有air的文件夹，同时创建单个log目录
        """
        dirs_ls = []
        for dirs in os.listdir(self.case_path):
            isdir = os.path.join(self.case_path, dirs)
            if os.path.isdir(isdir) and isdir.endswith(".air"):
                air_name = dirs.replace('.air', '')
                if 'all' in case_name or air_name in case_name:
                    script = os.path.join(self.case_path, isdir)
                    dirs_ls.append(script)
                    log = self.create_log(self.log_path, air_name)
                    CustomAirTestCase.log_list.append(log)
        return dirs_ls

    def do_run_by_pool(self, run_device, cases, log_path):
        """
        在指定设备上跑指定脚本
        :param run_device:
        :param script:
        :param log:
        :return:
        """
        run_device = 'Android:///' + run_device
        for script in cases:
            air_name = script.split(os.sep)[-1].replace('.air', '')
            log = os.path.join(log_path, air_name)
            print(run_device + ' run ' + script + '    ---->start')
            args = Namespace(device=run_device, log=log, recording=None, script=script)
            try:
                run_script(args, AirtestCase)
            except:
                pass
            print(run_device + ' run ' + script + '    ---->end')

    def doReport(self, results, total, report_name):
        """
        输出具体报告
        :param case_results:
        :param summary_message:
        :param device:
        :return:
        """
        report_path = os.path.join(self.workspace, 'report')
        if len(results) == 0:
            print("没有执行case")
            return
        else:
            env = jinja2.Environment(
                loader=jinja2.FileSystemLoader(os.path.join(self.workspace, 'templates')),
                extensions=(),
                autoescape=True
            )
            total["passRate"] = round(total["passNum"]*100/total["caseNum"], 2)
            template = env.get_template("summary_template.html")
            # log_path必须传相对路径，要不在jenkins上展示报告会报错
            log_path = '../log'
            # report_name 是根据设备命名的，如果report_name里有设备名的话，那log_path得加一层设备名
            if '_' in report_name:
                log_path = '../log/' + report_name.split('_')[-1].replace('.html', '')
            html = template.render({"case_results": results, "summary_message": total, "log_path": log_path})
            output_file = os.path.join(report_path, report_name)
            with io.open(output_file, 'w', encoding="utf-8") as f:
                f.write(html)
            print("报告文件: " + output_file)

    def delWithLogToReportByDevice(self, script_list, device):
        """
        根据日志信息产出报告，一
        :param workspace:个设备出一份日志
        :param script_list:
        :param log_path:
        :param device:
        :return:
        """
        summary_message = {}
        summary_message["caseNum"] = 0
        summary_message["passNum"] = 0
        log_path = os.path.join(self.log_path, device)
        case_results = []
        count = len(script_list)
        for i in range(count):
            script = script_list[i]
            air_name = script.split(os.sep)[-1].replace('.air', '')
            log = os.path.join(log_path, air_name)
            rpt = report.LogToHtml(script, log)
            output_file = log + os.sep + 'log.html'
            report_dir = '../../../report/report/'
            case_image_dir = '../../../air_case'
            rpt.report("log_template.html", report_dir, case_image_dir, output_file=output_file)
            result = {}
            result["name"] = air_name
            result["result"] = rpt.test_result
            if result["result"]:
                summary_message["passNum"] += 1
            start, end = self.get_case_runtime(log)
            result["time"] = (end - start)/1000 if end > start else 0
            case_results.append(result)
        summary_message["caseNum"] = count
        report_name = 'summary_' + device + '.html'
        self.doReport(case_results, summary_message, report_name)

    def delWithLogToReport(self, case_list):
        """
        读取运行case的日志，获取case数，case运行成功数等信息，生成html 报告
        :return:
        """
        count = len(CustomAirTestCase.log_list)
        for i in range(count):
            script = case_list[i]
            log = CustomAirTestCase.log_list[i]
            air_name = script.split(os.sep)[-1].replace('.air', '')
            rpt = report.LogToHtml(script, log)
            output_file = os.path.join(log, 'log.html')
            report_dir = '../../report/report/'
            case_image_dir = '../../air_case'
            try:
                rpt.report("log_template.html", report_dir, case_image_dir, output_file=output_file)
            except:
                pass
            result = {}
            result["name"] = air_name
            result["result"] = rpt.test_result
            if result["result"]:
                CustomAirTestCase.summary_message["passNum"] += 1
            try:
                start, end = self.get_case_runtime(log)
            except:
                start = 1
                end = 60
            result["time"] = (end - start) / 1000 if end > start else 0
            author = self.get_author(air_name, self.case_path)
            result["author"] = author
            CustomAirTestCase.case_results.append(result)
        CustomAirTestCase.summary_message["caseNum"] = count
        CustomAirTestCase.summary_message["passRate"] = round(CustomAirTestCase.summary_message["passNum"] \
                                                              * 100 / CustomAirTestCase.summary_message["caseNum"], 2)
        self.doReport(CustomAirTestCase.case_results, CustomAirTestCase.summary_message, 'summary.html')

    def run_case(self, run_case, case_name, job_url, case_scenario_name):
        """
        运行单个case
        :param case_name:
        :return: 返回case的运行结果集合，包括case名，case执行起止时间，供校验埋点的时候用
        """
        summary_message = {}
        summary_message["caseNum"] = 0
        summary_message["passNum"] = 0
        all_start = int(time.time() * 1000)
        fp = open(self.runtime_log, 'w+', encoding='utf-8')
        report_dir = '../../report/report/'
        static_root = report_dir
        case_image_dir = '../../air_case'
        lang = 'zh'
        plugin = ['airtest_selenium.report']
        # 聚合结果
        case_results = []
        # d获取所有用例集
        for filepath, dirnames, filenames in os.walk(self.case_path):
            for f in dirnames:
                if f.endswith(".air"):
                    # f为.air用例名称：demo.air
                    air_name = f.replace('.air', '')
                    if 'all' in case_name or air_name in case_name:
                        script = os.path.join(filepath, f)
                        # 创建日志
                        log = self.create_log(self.log_path, air_name)
                        output_file = os.path.join(log, 'log.html')
                        # global args
                        args = Namespace(device=None, log=log, recording=None, script=script)
                        start = int(time.time() * 1000)
                        try:
                            flag = False
                            i = 0
                            if "AutoTest_" in log:
                                while flag == False and i < 2:
                                    try:
                                        run_script(args, AirtestCase)
                                        flag = True
                                        i += 1
                                        print("yes,SUCCESS")
                                    except:
                                        i += 1
                                        pass
                            else:
                                run_script(args, AirtestCase)
                                flag = True
                                print("yes,SUCCESS")
                        except:
                            pass
                            print("oh, FAILED")
                        finally:
                            end = int(time.time() * 1000)
                            author = self.get_author(air_name, filepath)
                            fp.write(air_name + '\t' + str(start) + '\t' + str(end) + '\t' + author + '\n')
                            log_root = 'log/' + air_name
                            report.main(log_root, static_root, script, lang, plugin, report_dir, case_image_dir, output_file)
                            result = {}
                            result["name"] = air_name
                            result["result"] = flag
                            result["author"] = author
                            result["time"] = (end - start) / 1000 if end > start else 0
                            case_results.append(result)
                            if flag == False:
                                msg = confOP().getYamlValue("msg")
                                token = msg["dingding_msg"][0]
                                if "AutoTest_" in log and token != None:
                                    title = air_name
                                    if air_name in case_scenario_name:
                                        title = case_scenario_name[air_name] + "---" + air_name
                                    content = self.get_error_log_info(log)
                                    env = os.environ['ENV']
                                    if len(str(content)) > 20000:
                                        content = str(content)[1:300]
                                    self.dingding_send_markdown(env, title, content, job_url, author, token)
        print("case 执行完毕，开始生成报告")
        fp.close()
        seconds = (int(time.time() * 1000) - all_start) / 1000
        m, s = divmod(seconds, 60)
        summary_message["time"] = "%d分%d秒" % (m, s)
        new_case_result, summary_message = self.merge_run_result(run_case, case_results, summary_message)
        self.doReport(new_case_result, summary_message, 'summary.html')
        self.merge_log_txt(run_case, static_root, lang, plugin, report_dir, case_image_dir)
        print("报告已生成")

    def run_case_single(self, device, case_name):
        """
        运行单个case
        :param device:
        :param case_name:
        :return: 返回case的运行结果集合，包括case名，case执行起止时间，供校验埋点的时候用
        """
        summary_message = {}
        summary_message["caseNum"] = 0
        summary_message["passNum"] = 0
        all_start = int(time.time() * 1000)
        fp = open(self.runtime_log, 'w+', encoding='utf-8')
        # 聚合结果
        case_results = []
        # d获取所有用例集
        for f in os.listdir(self.case_path):
            if f.endswith(".air"):
                # f为.air用例名称：demo.air
                air_name = f.replace('.air', '')
                if 'all' in case_name or air_name in case_name:
                    script = os.path.join(self.case_path, f)
                    # 创建日志
                    log = self.create_log(self.log_path, air_name)
                    output_file = os.path.join(log, 'log.html')
                    # global args
                    dev = 'Android:///' + device
                    args = Namespace(device=dev, log=log, recording=None, script=script)
                    start = int(time.time() * 1000)
                    try:
                        run_script(args, AirtestCase)
                        summary_message["passNum"] += 1
                    except:
                        pass
                    finally:
                        end = int(time.time() * 1000)
                        author = self.get_author(air_name, self.case_path)
                        fp.write(device + '\t' + air_name + '\t' + str(start) + '\t' + str(end) + '\t' + author + '\n')
                        rpt = report.LogToHtml(script, log)
                        report_dir = '../../report/report/'
                        case_image_dir = '../../air_case'
                        rpt.report("log_template.html", report_dir, case_image_dir, output_file=output_file)
                        result = {}
                        result["name"] = air_name
                        result["result"] = rpt.test_result
                        result["time"] = (end - start) / 1000 if end > start else 0
                        case_results.append(result)
                        summary_message["caseNum"] += 1
        print("case 执行完毕，开始生成报告")
        fp.close()
        seconds = (int(time.time() * 1000) - all_start) / 1000
        m, s = divmod(seconds, 60)
        summary_message["time"] = "%d分%d秒" % (m, s)
        self.doReport(case_results, summary_message, 'summary.html')
        print("报告已生成")
        return True

    def run_case_by_Multi(self, device_list, case_name):
        """
        兼容性测试，case在每个机器上跑一遍
        :param device_list:
        :param case_name:
        :return:
        """
        all_start = int(time.time() * 1000)
        p = Pool(len(device_list))
        # 获取所有需要执行的用例集
        script_list = self.get_cases_and_log(case_name, device_list)
        print("任务列表：")
        print(script_list)
        for device in device_list:
            # 设置进程数和设备数一样
            try:
                p.apply_async(self.do_run_by_pool, args=(device, script_list, os.path.join(self.log_path, device)))
            except:
                pass
        p.close()
        p.join()
        print("all subprocesses done")
        seconds = (int(time.time() * 1000) - all_start) / 1000
        m, s = divmod(seconds, 60)
        CustomAirTestCase.summary_message["time"] = "%d分%d秒" % (m, s)
        for device in device_list:
            self.delWithLogToReportByDevice(script_list, device)

    def run_case_by_distri(self, device_list, case_name):
        """
        多进程跑case，将任务平均分给不同的设备，多进程跑，都跑完后，读取各case的log.txt 文件，获取case的开始结束时间信息
        :param device_list
        :param case_name:
        :return:
        """
        all_start = int(time.time() * 1000)
        # 获取所有需要执行的用例集
        script_list = self.get_all_dir(case_name)
        device_count = len(device_list)
        #把任务分配给不同的设备，分布式跑就是不同机器跑不同任务最终完成所有任务
        case_list = self.assign_tasks(script_list, device_count)
        print("任务列表：")
        print(case_list)
        # 记录case 及脚本对应关系
        case_dict = {}
        #设置进程数和设备数一样
        p = Pool(device_count)
        for i in range(device_count):
            run_device = device_list[i]
            cases = case_list[i]
            case_dict[run_device] = cases
            try:
                p.apply_async(self.do_run_by_pool, args=(run_device, cases, self.log_path))
            except:
                pass
        p.close()
        p.join()
        print("all SubProcesses done")
        seconds = (int(time.time() * 1000) - all_start) /1000
        m, s = divmod(seconds, 60)
        CustomAirTestCase.summary_message["time"] = "%d分%d秒" % (m, s)
        self.delWithLogToReport(script_list, case_dict)

    def analysis_air_file(self, case_name, case_path, new_air_name):
        """
        解析需要执行的air文件，将场景和场景之间隔开
        :param case_name: 需要分开场景的air文件
        :return:
        """
        case_name_list = []
        file_name = case_path + os.sep + case_name + '.py'
        pyfile = open(file_name, 'r', encoding='utf-8')
        lines = pyfile.readlines()
        for line in lines:
            line = line.replace(" ", "").replace("\n", "")
            if re.match("^场景", line):
                line = line.replace("\\", "").replace("/", "").replace(":", "").replace("*", "").replace("?", "").replace("\"", "").replace("<", "").replace(">", "").replace("|", "")
                if line in new_air_name:
                    line = line + str(random.randint(1, 500)) + str(random.choice("abcdefghijklmnopqrstuvwxyz"))
                case_name_list.append(line)
        pyfile.close()
        """
          如果含有多条(>1)场景，则对场景进行代码块划分
        """
        if len(case_name_list) > 1:
            i = 0
            header_file = open(case_path + os.sep + 'header.py', 'w', encoding='utf-8')
            for line in lines:
                if re.match("^场景", line.replace(" ", "").replace("\n", "")):
                    new_file = open(case_path + os.sep + case_name_list[i] + '.py', 'w', encoding='utf-8')
                    new_file.write(line)
                    new_file.close()
                    i += 1
                else:
                    if i == 0:
                        header_file.write(line)
                    else:
                        new_file = open(case_path + os.sep + case_name_list[i-1] + '.py', 'a+', encoding='utf-8')
                        new_file.write(line)
                        new_file.close()
            header_file.close()
            new_air_name.extend(case_name_list)
            return case_name_list, new_air_name
        else:
            case_name_list = []
            if case_name in new_air_name:
                case_name = case_name + str(random.randint(1, 500)) + str(random.choice("abcdefghijklmnopqrstuvwxyz"))
            case_name_list.append(case_name)
            new_air_name.extend(case_name_list)
            return case_name_list, new_air_name

    def merge_new_file(self, case_list):
        """
        将公共文件和场景文件合并成一个新的air文件
        :param case_list:
        :return:
        """
        new_case_list = []
        new_air_name = []
        case_scenario_name = {}
        for i in range(len(case_list)):
            case_hash = {}
            air_name = case_list[i]["air_name"]
            air_path = case_list[i]["air_path"]
            module_name = case_list[i]["module"]
            case_hash["run_case"] = air_name
            case_hash["module"] = module_name
            case_name_list, new_air_name = self.analysis_air_file(air_name, air_path, new_air_name)
            if len(case_name_list) > 1:
                case_hash["scene_run_cases"] = case_name_list
                for j in range(len(case_name_list)):
                    case_scenario_name[case_name_list[j]] = air_name
                    if not os.path.exists(air_path):
                        os.mkdir(air_path)
                    header_file = open(air_path + os.sep + 'header.py', 'r', encoding='utf-8')
                    header_lines = header_file.readlines()
                    header_file.close()
                    new_file = open(air_path + os.sep + case_name_list[j] + '.py', 'r', encoding='utf-8')
                    new_file_lines = new_file.readlines()
                    last_line = new_file_lines[-1]
                    if re.match("^[\"]+$", last_line):
                        new_file_lines = new_file_lines[:-1]
                    new_file.close()
                    dir_name = self.case_path + os.sep + module_name + os.sep + case_name_list[j] + ".air"
                    if not os.path.exists(dir_name):
                        os.mkdir(dir_name)
                    new_air = open(dir_name + os.sep + case_name_list[j] + '.py', 'w', encoding='utf-8')
                    new_air.writelines(header_lines)
                    for line in new_file_lines:
                        new_air.write(line)
                    new_air.close()
                    os.remove(air_path + os.sep + case_name_list[j] + '.py')
                os.remove(air_path + os.sep + 'header.py')
            new_case_list.append(case_hash)
        return new_case_list, new_air_name, case_scenario_name

    def merge_run_result(self, run_case_list, case_result, summary_message):
        """
        将场景执行结果合并，确定最后场景执行的最后状态，成功or失败
        :return:
        """
        new_case_result = []
        """
        遍历跑的所有用例，包括拆分出来的所有场景
        判断每一个list中是否存在scene_run_cases，
        如果存在，则一个接口中有多个场景，遍历scene_run_cases，去case_result中找执行的结果，进行合并
        如果不存在，则将执行结果赋值到新的结果中
        """
        count = 0
        summary_message["result"] = True
        for i in range(len(run_case_list)):
            new_dict_result = {}
            json_case = run_case_list[i]
            if 'scene_run_cases' in json_case:
                time = 0
                new_dict_result["result"] = True
                scene_names = json_case["scene_run_cases"]
                new_dict_result["name"] = json_case["run_case"]
                # 遍历scene_run_cases
                break_flag = False
                for m in range(len(scene_names)):
                    air_name = scene_names[m]
                    for j in range(len(case_result)):
                        dict_case = case_result[j]
                        if air_name == dict_case["name"]:
                            new_dict_result["author"] = dict_case["author"]
                            time = float(time) + float(dict_case["time"])
                            if dict_case["result"] == False:
                                new_dict_result["result"] = False
                                count += 1
                                break_flag = True
                                summary_message["result"] = False
                            break
                    if break_flag:
                        break
                new_dict_result["time"] = time
                new_case_result.append(new_dict_result)
            else:
                air_name = json_case["run_case"]
                for j in range(len(case_result)):
                    dict_case = case_result[j]
                    if air_name == dict_case["name"]:
                        if dict_case["result"] == False:
                            count += 1
                        new_case_result.append(dict_case)
                        break
        summary_message["caseNum"] = len(run_case_list)
        summary_message["passNum"] = len(run_case_list) - count
        return new_case_result, summary_message

    def merge_log_txt(self, run_case_list, static_root, lang, plugin, report_dir, case_image_dir):
        """
        将log.txt内容合并
        :param run_case_list:
        :return:
        """
        for i in range(len(run_case_list)):
            json_case = run_case_list[i]
            module_name = json_case["module"]
            if 'scene_run_cases' in json_case:
                air_name = json_case["run_case"]
                script = self.case_path + os.sep + module_name + os.sep + air_name + ".air"
                log_root = "log" + os.sep + air_name
                air_log_path = self.log_path + os.sep + air_name
                if not os.path.exists(air_log_path):
                    os.mkdir(air_log_path)
                new_log = open(self.log_path + os.sep + air_name + os.sep + 'log.txt', 'w', encoding='utf-8')
                scene_run_cases = json_case["scene_run_cases"]
                for j in range(len(scene_run_cases)):
                    sub_air_name = scene_run_cases[j]
                    try:
                        sub_log = open(self.log_path + os.sep + sub_air_name + os.sep + 'log.txt', 'r', encoding='utf-8')
                        lines = sub_log.readlines()
                        if len(lines) > 0:
                            json_line = json.loads(lines[0])
                            total_time = str(json_line["time"])
                            if "start_time" in json_line["data"]:
                                start_time = json_line["data"]["start_time"]
                                end_time = json_line["data"]["end_time"]
                            else:
                                start_time = "1603779572.984517"
                                end_time = "1603779572.984517"
                        else:
                            total_time = "1603779572.984517"
                            start_time = "1603779572.984517"
                            end_time = "1603779572.984517"
                        new_log.write('{"tag": "function", "depth": 1, "time": %s, "data": {"name": "assert_equal", "call_args": {"first": "autotest", "second": "autotest", "msg": ""}, "start_time": %s, "ret": null, "end_time": %s}, "scene_name": "%s"}\n' % (total_time, start_time, end_time, str(sub_air_name)))
                        new_log.writelines(lines)
                        sub_log.close()
                        new_air_path = self.case_path + os.sep + module_name
                        os.remove(new_air_path + os.sep + sub_air_name + ".air" + os.sep + sub_air_name + ".py")
                        shutil.rmtree(new_air_path + os.sep + sub_air_name + ".air")
                    except Exception as e:
                        print("mergeLogTxt: ", e)
                        new_air_path = self.case_path + os.sep + module_name
                        os.remove(new_air_path + os.sep + sub_air_name + ".air" + os.sep + sub_air_name + ".py")
                        shutil.rmtree(new_air_path + os.sep + sub_air_name + ".air")
                new_log.close()
                output_file = self.log_path + os.sep + air_name + os.sep + "log.html"
                report.main(log_root, static_root, script, lang, plugin, report_dir, case_image_dir, output_file)

    def run_by_scenario(self, module_name, case_name, scenario_name):
        case_results = []
        """
        按照一条用例中的场景执行
        :return:
        """
        case_path = self.case_path + os.sep + module_name + os.sep + case_name + ".air"
        case_name_list = self.analysis_air_file(case_name, case_path, [])
        for i in range(len(case_name_list)):
            if scenario_name in case_name_list[i]:
                scenario_name = case_name_list[i]
        script = self.case_path + os.sep + module_name + os.sep + scenario_name + ".air"
        air_path = self.case_path + os.sep + module_name + os.sep + scenario_name + ".air"
        if not os.path.exists(air_path):
            os.mkdir(air_path)
        header_file = open(case_path + os.sep + 'header.py', 'r', encoding='utf-8')
        header_lines = header_file.readlines()
        header_file.close()
        new_file = open(case_path + os.sep + scenario_name + '.py', 'r', encoding='utf-8')
        new_file_lines = new_file.readlines()
        last_line = new_file_lines[-1]
        if re.match("^[\"]+$", last_line):
            new_file_lines = new_file_lines[:-1]
        new_file.close()
        dir_name = self.case_path + os.sep + module_name + os.sep + scenario_name + ".air"
        if os.path.isdir(dir_name):
            new_air = open(dir_name + os.sep + scenario_name + '.py', 'w', encoding='utf-8')
            new_air.writelines(header_lines)
            for line in new_file_lines:
                new_air.write(line)
            new_air.close()
        for j in range(len(case_name_list)):
            os.remove(case_path + os.sep + case_name_list[j] + '.py')
        os.remove(case_path + os.sep + 'header.py')
        summary_message = {}
        summary_message["caseNum"] = 0
        summary_message["passNum"] = 0
        fp = open(self.runtime_log, 'w+', encoding='utf-8')
        # 创建日志
        log = self.create_log(self.log_path, scenario_name)
        output_file = os.path.join(log, 'log.html')
        # global args
        args = Namespace(device=None, log=log, recording=None, script=script)
        start = int(time.time() * 1000)
        try:
            run_script(args, AirtestCase)
            summary_message["passNum"] += 1
        except:
            pass
        finally:
            end = int(time.time() * 1000)
            author = self.get_author(scenario_name, self.case_path + os.sep + module_name)
            fp.write(scenario_name + '\t' + str(start) + '\t' + str(end) + '\t' + author + '\n')
            rpt = report.LogToHtml(script, log)
            report_dir = '../../report/report/'
            case_image_dir = '../../air_case'
            rpt.report("log_template.html", report_dir, case_image_dir, output_file=output_file)
            result = {}
            result["name"] = scenario_name
            result["result"] = rpt.test_result
            result["time"] = (end - start) / 1000 if end > start else 0
            case_results.append(result)
            summary_message["caseNum"] += 1
        self.doReport(case_results, summary_message, 'summary.html')
        os.remove(dir_name + os.sep + scenario_name + ".py")
        shutil.rmtree(dir_name)
        print("报告已生成")
        return True

    def insert_api_path_to_cloud(self, case_list):
        for i in range(len(case_list)):
            every_case = case_list[i]















