Example #1
0
def main():
    now = time.strftime("%Y-%m-%d %H_%M_%S")
    filename = REPORT_DIR + '/' + now + do_config("report", "html_report_name")
    file = open(filename, 'wb')
    runner = HTMLTestRunnerNew.HTMLTestRunner(
        stream=file,
        verbosity=do_config("report", "verbosity"),
        title=do_config("report", "title"),
        description=do_config("report", "description"),
        tester=do_config("report", "tester"))
    runner.run(suite)
    file.close()  # 关闭文件对象
Example #2
0
    def test_invest(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.invest_parametrization(nt.data)
        actual_response = self.one_request(nt.method, url, data1)  # 发起投标请求
        try:  # 判断状态码是否200,异常状态不用做返回值的断言
            self.assertEqual(200,
                             actual_response.status_code,
                             msg="测试【{}】时,请求失败!状态码为【{}】".format(
                                 nt.title, actual_response.status_code))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.invest_excel.write_excel(case_id + 1, actual_response.text,
                                          do_config("msg", "fail_msg"))
            raise e

        if actual_response.json().get('msg') == "加标成功":  # 解决用例对loadid的依赖关系
            check_sql = nt.check_sql
            if check_sql:
                sql = ReText.invest_parametrization(check_sql)
                loan_id = self.do_mysql(sql)['Id']
                # ReText.loan_id = loan_id  # 查库取出加标后最大id,动态为Retext类生成类属性
                # 反射解决了不能互相导包,全局变量值更新的问题
                setattr(ReText, "loan_id", loan_id)  # 反射,动态为对象(类)生成实例属性(类属性)

        expected = json.loads(nt.expected, encoding='utf8')  # 字典类型的期望值
        try:
            self.assertEqual(expected,
                             actual_response.json(),
                             msg="执行[{}]失败".format(nt.title))
            if expected.get(
                    "msg") == "竞标成功":  # 竞标成功的用例,断言数据库投资金额是否正确。用户剩余金额也可以断言,未写
                check_sql = nt.check_sql
                sql = ReText.invest_parametrization(check_sql)
                actual_amount = self.do_mysql(sql).get(
                    'Amount')  # 查库取出投资人投资记录,是Decimal类型,需要转换类型
                actual_amount = round(float(actual_amount), 2)
                expect_amount = eval(data1).get(
                    'amount')  # data1为字符串类型的字典, get期望充值金额
                self.assertEqual(
                    expect_amount,
                    actual_amount,
                    msg="执行[{}]失败,数据库中投资的金额错误,期望投资{},实际投资{}".format(
                        nt.title, expect_amount, actual_amount))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.invest_excel.write_excel(case_id + 1, actual_response.text,
                                          do_config("msg", "fail_msg"))
            raise e
        else:
            self.invest_excel.write_excel(case_id + 1, actual_response.text,
                                          do_config("msg", "pass_msg"))
Example #3
0
    def test_login(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.recharge_parametrization(nt.data)
        check_sql = nt.check_sql
        if check_sql:
            sql = ReText.recharge_parametrization(check_sql)
            # sql = "SELECT `LeaveAmount` FROM future.`member` WHERE `Id`=%s"

            before_amount = self.do_mysql(sql)[
                'LeaveAmount']  # 查库取出投资人充值前的金额,是Decimal类型,需要转换类型
            before_amount = round(float(before_amount), 2)
        actual_response = self.one_request(nt.method, url, data1)  # 发起充值请求
        try:  # 判断状态码是否200,异常状态不用做返回值的断言
            self.assertEqual(200,
                             actual_response.status_code,
                             msg="测试【{}】时,请求失败!状态码为【{}】".format(
                                 nt.title, actual_response.status_code))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "fail_msg"))
            raise e

        try:
            self.assertIn(nt.expected,
                          actual_response.text,
                          msg="执行[{}]失败".format(nt.title))  # assertIn必须是两个序列类型
            if check_sql:
                sql = ReText.recharge_parametrization(check_sql)
                after_amount = self.do_mysql(sql)[
                    'LeaveAmount']  # 查库取出投资人充值前的金额,是Decimal类型,需要转换类型
                after_amount = round(float(after_amount), 2)
                expect_amount = eval(data1).get(
                    'amount')  # data1为字符串类型的字典, get期望充值金额
                actual_amount = round(after_amount - before_amount,
                                      2)  # 实际充值金额

                self.assertEqual(
                    expect_amount,
                    actual_amount,
                    msg="执行[{}]失败,数据库中充值的金额错误,期望充值{},实际充值{}".format(
                        nt.title, expect_amount, actual_amount))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "fail_msg"))
            raise e
        else:
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "pass_msg"))
Example #4
0
class TestRegister(unittest.TestCase):
    base_url = do_config("interface", "base_url")
    login_excel = ExcelHandler(CASE_DATA_DIR, 'login')

    @classmethod
    def setUpClass(cls):
        cls.one_request = HttpRequests()
        do_logger.info("\n{:=^50s}".format("开始执行登录接口用例"))

    @classmethod
    def tearDownClass(cls):
        cls.one_request.close()
        do_logger.info("\n{:=^50s}".format("执行登录接口用例结束"))

    @data(*login_excel.read_excel())
    def test_login(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.login_parametrization(nt.data)
        expected = json.loads(nt.expected)
        actual = self.one_request(nt.method, url, data1)
        try:
            self.assertEqual(expected,
                             actual.json(),
                             msg="执行[{}]失败".format(nt.title))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.login_excel.write_excel(case_id + 1, actual.text,
                                         do_config("msg", "fail_msg"))
            raise e
        else:
            self.login_excel.write_excel(case_id + 1, actual.text,
                                         do_config("msg", "pass_msg"))
Example #5
0
 def __init__(self, isconsole=True):
     self.logger = logging.getLogger(do_config('log',
                                               'logger_name'))  # 1 定义日志器的名字
     self.logger.setLevel(logging.DEBUG)  # 2 指定日志收集器的日志等级
     file_log_dir = os.path.join(LOG_DIR,
                                 do_config("log",
                                           "log_file_name"))  # 日志文件路径
     # 有bug,PermissionError:[WinError 32] 另一个程序正在使用日志文件
     # 解决方案1:每个模块都实例化一个日志器对象
     # 方案2 安装并导入第三方模块 pip install concurrent-log-handler
     # file_handle = RotatingFileHandler(file_log_dir,
     #                                   maxBytes=do_config('log', 'maxBytes'),
     #                                   backupCount=do_config('log', 'backupCount'), encoding='utf8')  # 3 定义文件handle对象,日志回滚
     file_handle = ConcurrentRotatingFileHandler(
         file_log_dir,
         maxBytes=do_config('log', 'maxBytes'),
         backupCount=do_config('log', 'backupCount'),
         encoding='utf8')  # 3 定义文件handle对象,日志回滚
     file_handle.setLevel(do_config(
         'log', 'file_handle_level'))  # 4 指定文件handle对象的日志等级
     formatter = logging.Formatter(do_config('log',
                                             'formatter'))  # 5 定义日志格式对象
     file_handle.setFormatter(formatter)  # 6 设置文件handle格式
     self.logger.addHandler(file_handle)  # 7 日志收集器与handle对接
     if isinstance(isconsole, bool):
         if isconsole:
             console_handle = logging.StreamHandler()  # 定义控制台handle对象
             console_handle.setLevel(
                 do_config('log',
                           'console_handle_level'))  # 设置控制台handle对象的日志等级
             console_handle.setFormatter(formatter)  # 设置控制台handle格式
             self.logger.addHandler(console_handle)  # 日志收集器与控制台handle对接
     else:
         raise ValueError("isconsole为布尔类型")
Example #6
0
 def test_login(self, nt):
     case_id = nt.case_id
     url = self.base_url + nt.url
     data1 = ReText.login_parametrization(nt.data)
     expected = json.loads(nt.expected)
     actual = self.one_request(nt.method, url, data1)
     try:
         self.assertEqual(expected,
                          actual.json(),
                          msg="执行[{}]失败".format(nt.title))
     except AssertionError as e:
         do_logger.error('用例执行失败!具体异常为:{}'.format(e))
         self.login_excel.write_excel(case_id + 1, actual.text,
                                      do_config("msg", "fail_msg"))
         raise e
     else:
         self.login_excel.write_excel(case_id + 1, actual.text,
                                      do_config("msg", "pass_msg"))
Example #7
0
class TestAdd(unittest.TestCase):
    base_url = do_config("interface", "base_url")
    add_excel = ExcelHandler(CASE_DATA_DIR, 'add')

    @classmethod
    def setUpClass(cls):
        cls.one_request = HttpRequests()
        cls.do_mysql = MysqlHandler()
        do_logger.info("\n{:=^50s}".format("开始执行加标接口用例"))

    @classmethod
    def tearDownClass(cls):
        cls.one_request.close()
        do_logger.info("\n{:=^50s}".format("执行加标接口用例结束"))
        cls.do_mysql.close()

    @data(*add_excel.read_excel())
    def test_login(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.add_parametrization(nt.data)
        check_sql = nt.check_sql
        if check_sql:
            sql = ReText.add_parametrization(check_sql)
            before_id = self.do_mysql(sql)['Id']  # 查库取出加标前最大id,可能是null
        actual_response = self.one_request(nt.method, url, data1)  # 发起加标请求
        try:  # 判断状态码是否200,异常状态不用做返回值的断言
            self.assertEqual(200,
                             actual_response.status_code,
                             msg="测试【{}】时,请求失败!状态码为【{}】".format(
                                 nt.title, actual_response.status_code))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "fail_msg"))
            raise e

        try:
            self.assertEqual(json.loads(nt.expected, encoding='utf8'),
                             actual_response.json(),
                             msg="执行[{}]失败".format(nt.title))
            if check_sql:
                sql = ReText.add_parametrization(check_sql)
                after_id = self.do_mysql(sql)['Id']  # 查库取出加标后最大id
                # 最大标id不一致,则表明数据插入成功,断言成功
                self.assertNotEqual(before_id,
                                    after_id,
                                    msg="执行[{}]失败,数据库中插入加标记录失败!".format(
                                        nt.title))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "fail_msg"))
            raise e
        else:
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "pass_msg"))
Example #8
0
    def test_login(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.add_parametrization(nt.data)
        check_sql = nt.check_sql
        if check_sql:
            sql = ReText.add_parametrization(check_sql)
            before_id = self.do_mysql(sql)['Id']  # 查库取出加标前最大id,可能是null
        actual_response = self.one_request(nt.method, url, data1)  # 发起加标请求
        try:  # 判断状态码是否200,异常状态不用做返回值的断言
            self.assertEqual(200,
                             actual_response.status_code,
                             msg="测试【{}】时,请求失败!状态码为【{}】".format(
                                 nt.title, actual_response.status_code))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "fail_msg"))
            raise e

        try:
            self.assertEqual(json.loads(nt.expected, encoding='utf8'),
                             actual_response.json(),
                             msg="执行[{}]失败".format(nt.title))
            if check_sql:
                sql = ReText.add_parametrization(check_sql)
                after_id = self.do_mysql(sql)['Id']  # 查库取出加标后最大id
                # 最大标id不一致,则表明数据插入成功,断言成功
                self.assertNotEqual(before_id,
                                    after_id,
                                    msg="执行[{}]失败,数据库中插入加标记录失败!".format(
                                        nt.title))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "fail_msg"))
            raise e
        else:
            self.add_excel.write_excel(case_id + 1, actual_response.text,
                                       do_config("msg", "pass_msg"))
Example #9
0
 def __init__(self,
              filename,
              sheetname='',
              max_col=do_config('excel', 'max_column')):
     """
     初始化
     :param filename: excel文件路径名
     :param sheetname: 需要定位的表单名
     :param max_col:  读取的最大列数(扣除待写的列)
     """
     self.filename = filename  # 从常量文件中读取excel绝对路径
     self.sheetname = sheetname
     self.data_list = []
     self.wb = load_workbook(self.filename)
     self.ws = self.wb[sheetname] if sheetname != '' else self.wb.active
     self.max_col = max_col
     self.data_header = tuple(
         self.ws.iter_rows(max_row=1,
                           max_col=self.max_col,
                           values_only=True))[0]
     self.Cases = namedtuple("Cases", self.data_header)
Example #10
0
 def write_excel(self, row, *data_tuple):
     """
     写入excel
     :param row: 单元格的行号 int
     :param data_tuple: 待写入的值
     """
     other_wb = load_workbook(self.filename)
     other_ws = other_wb[self.sheetname]
     if isinstance(row, int) and (1 < row <= other_ws.max_row):
         try:
             columns = do_config(
                 'excel', 'columns',
                 iseval=True)  # 读取配置文件中单元格的列号,类型可以为int,list,tuple,''
         except SyntaxError:  # columns选项值为空时或者类型不正确时,默认写入列号为max_col的后两个
             if len(data_tuple) != 2:
                 do_logger.error('写入的列数与值的个数不匹配,写入失败!')
                 raise IndexError('tuple index out of range')
             other_ws.cell(row, self.max_col + 1, value=data_tuple[0])
             other_ws.cell(row, self.max_col + 2, value=data_tuple[1])
             other_wb.save(self.filename)
         else:
             if isinstance(columns, (list, tuple)):
                 sort_columns = list(set(columns))
                 sort_columns.sort()
                 if len(data_tuple) != len(sort_columns):
                     do_logger.error('写入的列数与值的个数不匹配,写入失败!')
                     raise IndexError('tuple index out of range')
                 for i in sort_columns:
                     other_ws.cell(row,
                                   i,
                                   value=data_tuple[sort_columns.index(i)])
                 other_wb.save(self.filename)
             elif isinstance(columns, int):
                 other_ws.cell(row, columns, value=data_tuple[0])
                 other_wb.save(self.filename)
     else:
         do_logger.error('传入的行号错误,行号必须是大于1的整数!写入失败!')
Example #11
0
def create_new_user(regname, pwd="12345678"):
    handle_mysql = MysqlHandler()
    request = HttpRequests()
    sql = "SELECT `Id` FROM future.`member` WHERE `MobilePhone`=%s"
    url = do_config('interface', 'base_url') + "/member/register"
    while True:
        phone = handle_mysql.create_unregist_phone()
        data = {"mobilephone": phone, "pwd": pwd, "regname": regname}
        request('post', url, data)
        result = handle_mysql(sql, (phone, ))
        if result:
            id = result['Id']
            break
    user_dict = {
        regname: {
            'id': id,
            'regname': regname,
            'pwd': pwd,
            'phone': phone
        }
    }
    request.close()
    handle_mysql.close()
    return user_dict
Example #12
0
class TestRecharge(unittest.TestCase):
    base_url = do_config("interface", "base_url")
    recharge_excel = ExcelHandler(CASE_DATA_DIR, 'recharge')

    @classmethod
    def setUpClass(cls):
        cls.one_request = HttpRequests()
        user_data = {
            "mobilephone": user_config("invest_user", "phone"),
            "pwd": user_config("invest_user", "pwd")
        }
        cls.one_request('post', cls.base_url + '/member/login', user_data)
        cls.do_mysql = MysqlHandler()
        do_logger.info("\n{:=^50s}".format("开始执行充值接口用例"))

    @classmethod
    def tearDownClass(cls):
        cls.one_request.close()
        do_logger.info("\n{:=^50s}".format("执行充值接口用例结束"))
        cls.do_mysql.close()

    @data(*recharge_excel.read_excel())
    def test_login(self, nt):
        case_id = nt.case_id
        url = self.base_url + nt.url
        data1 = ReText.recharge_parametrization(nt.data)
        check_sql = nt.check_sql
        if check_sql:
            sql = ReText.recharge_parametrization(check_sql)
            # sql = "SELECT `LeaveAmount` FROM future.`member` WHERE `Id`=%s"

            before_amount = self.do_mysql(sql)[
                'LeaveAmount']  # 查库取出投资人充值前的金额,是Decimal类型,需要转换类型
            before_amount = round(float(before_amount), 2)
        actual_response = self.one_request(nt.method, url, data1)  # 发起充值请求
        try:  # 判断状态码是否200,异常状态不用做返回值的断言
            self.assertEqual(200,
                             actual_response.status_code,
                             msg="测试【{}】时,请求失败!状态码为【{}】".format(
                                 nt.title, actual_response.status_code))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "fail_msg"))
            raise e

        try:
            self.assertIn(nt.expected,
                          actual_response.text,
                          msg="执行[{}]失败".format(nt.title))  # assertIn必须是两个序列类型
            if check_sql:
                sql = ReText.recharge_parametrization(check_sql)
                after_amount = self.do_mysql(sql)[
                    'LeaveAmount']  # 查库取出投资人充值前的金额,是Decimal类型,需要转换类型
                after_amount = round(float(after_amount), 2)
                expect_amount = eval(data1).get(
                    'amount')  # data1为字符串类型的字典, get期望充值金额
                actual_amount = round(after_amount - before_amount,
                                      2)  # 实际充值金额

                self.assertEqual(
                    expect_amount,
                    actual_amount,
                    msg="执行[{}]失败,数据库中充值的金额错误,期望充值{},实际充值{}".format(
                        nt.title, expect_amount, actual_amount))
        except AssertionError as e:
            do_logger.error('用例执行失败!具体异常为:{}'.format(e))
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "fail_msg"))
            raise e
        else:
            self.recharge_excel.write_excel(case_id + 1, actual_response.text,
                                            do_config("msg", "pass_msg"))