def open_scene(self, scene_name, scene_data): self.clear_scene() self.set_current_scene_name(scene_name) logger.info("Open scene : %s" % scene_name) camera_datas = scene_data.get('cameras', []) for camera_data in camera_datas: self.addCamera(**camera_data) self.main_camera = self.get_camera(0) light_datas = scene_data.get('lights', []) for light_data in light_datas: self.addLight(**light_data) self.main_light = self.get_light(0) light_probe_datas = scene_data.get('light_probes', []) if light_probe_datas: for light_probe_data in light_probe_datas: self.addLightProbe(**light_probe_data) else: self.addLightProbe() self.main_light_probe = self.get_light_probe(0) self.sky = Sky() self.atmosphere = Atmosphere() for object_data in scene_data.get('static_actors', []): self.addObject(**object_data) for object_data in scene_data.get('skeleton_actors', []): self.addObject(**object_data) self.post_open_scene()
def compile_from_source(self, shader_codes: dict): """ :param shader_codes: {GL_VERTEX_SHADER:code_string, GL_FRAGMENT_SHADER:code_string, } """ shaders = [] for shader_type in shader_codes: shader = self.compile(shader_type, shader_codes[shader_type]) if shader is not None: logger.info("Compile %s %s." % (self.name, shader_type)) shaders.append(shader) self.program = glCreateProgram() # glProgramParameteri(self.program, GL_PROGRAM_SEPARABLE, GL_TRUE) glProgramParameteri(self.program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE) for shader in shaders: glAttachShader(self.program, shader) glLinkProgram(self.program) for shader in shaders: glDetachShader(self.program, shader) glDeleteShader(shader)
def __init__(self, material_instance_name, **data): self.valid = False self.isNeedToSave = False logger.info("Load Material Instance : " + material_instance_name) self.name = material_instance_name self.shader_name = data.get('shader_name', 'default') self.material = None self.material_name = data.get('material_name', 'default') self.macros = copy.copy(data.get('macros', OrderedDict())) self.linked_uniform_map = dict() self.linked_material_component_map = dict() self.Attributes = Attributes() material = data.get('material') # link uniform_buffers and uniform_data self.set_material(material) if self.material: # and set the loaded uniform data. uniform_datas = data.get('uniform_datas', {}) for data_name, data_value in uniform_datas.items(): self.set_uniform_data_from_string(data_name, data_value) else: logger.error("%s material instance has no material." % self.name) return self.valid = True
def addLightProbe(self, **light_probe_data): light_probe_data['name'] = self.generateObjectName( light_probe_data.get('name', 'light_probe')) light_probe_data['model'] = self.resource_manager.getModel('sphere') logger.info("add Light Probe : %s" % light_probe_data['name']) light_probe = LightProbe(**light_probe_data) self.regist_object(light_probe) return light_probe
def addLight(self, **light_data): light_data['name'] = self.generateObjectName( light_data.get('name', 'light')) light_data['model'] = self.resource_manager.getModel('Cube') logger.info("add Light : %s" % light_data['name']) light = Light(**light_data) self.regist_object(light) return light
def initialize(self, core_manager): logger.info("initialize " + GetClassName(self)) self.core_manager = core_manager self.resource_manager = core_manager.resource_manager self.sceneLoader = self.resource_manager.sceneLoader self.renderer = core_manager.renderer # new scene self.new_scene()
def addCamera(self, **camera_data): camera_data['name'] = self.generateObjectName( camera_data.get('name', 'camera')) camera_data['model'] = self.resource_manager.getModel('Cube') logger.info("add Camera : %s" % camera_data['name']) camera = Camera(scene_manager=self, **camera_data) camera.initialize() self.regist_object(camera) return camera
def CreateVertexArrayBuffer(geometry_data): geometry_name = geometry_data.get('name', '') logger.info("Load %s geometry." % geometry_name) vertex_count = len(geometry_data.get('positions', [])) if vertex_count == 0: logger.error("%s geometry has no position data." % geometry_name) return None positions = np.array(geometry_data['positions'], dtype=np.float32) if 'indices' not in geometry_data: logger.error("%s geometry has no index data." % geometry_name) return None indices = np.array(geometry_data['indices'], dtype=np.uint32) bone_indicies = np.array(geometry_data.get('bone_indicies', []), dtype=np.float32) bone_weights = np.array(geometry_data.get('bone_weights', []), dtype=np.float32) colors = np.array(geometry_data.get('colors', []), dtype=np.float32) if len(colors) == 0: colors = np.array([[1.0, 1.0, 1.0, 1.0]] * vertex_count, dtype=np.float32) texcoords = np.array(geometry_data.get('texcoords', []), dtype=np.float32) if len(texcoords) == 0: texcoords = np.array([[0.0, 0.0]] * vertex_count, dtype=np.float32) normals = np.array(geometry_data.get('normals', []), dtype=np.float32) if len(normals) == 0: normals = np.array([ [0.0, 0.0, 1.0], ] * vertex_count, dtype=np.float32) tangents = np.array(geometry_data.get('tangents', []), dtype=np.float32) if len(tangents) == 0: tangents = compute_tangent(positions, texcoords, normals, indices) geometry_data['tangents'] = tangents.tolist() if 0 < len(bone_indicies) and 0 < len(bone_weights): vertex_array_buffer = VertexArrayBuffer(geometry_name, [ positions, colors, normals, tangents, texcoords, bone_indicies, bone_weights ], indices) else: vertex_array_buffer = VertexArrayBuffer( geometry_name, [positions, colors, normals, tangents, texcoords], indices) return vertex_array_buffer
def __init__(self, mesh_name, **mesh_data): logger.info("Load %s : %s" % (GetClassName(self), mesh_name)) self.name = mesh_name self.instance_location_model = -1 self.skeletons = [] for i, skeleton_data in enumerate(mesh_data.get('skeleton_datas', [])): skeleton = Skeleton(index=i, **skeleton_data) self.skeletons.append(skeleton) if self.has_bone(): # skeletal actor self.instance_location_model = 7 else: # static actor self.instance_location_model = 5 self.animations = [] for i, animation_data in enumerate(mesh_data.get( 'animation_datas', [])): if animation_data: animation_name = "%s_%s" % (self.name, self.skeletons[i].name) animation = Animation(name=animation_name, index=i, skeleton=self.skeletons[i], animation_data=animation_data) self.animations.append(animation) else: self.animations.append(None) self.geometries = [] for i, geometry_data in enumerate(mesh_data.get('geometry_datas', [])): vertex_buffer = CreateVertexArrayBuffer(geometry_data) if vertex_buffer: # create model matrix instance buffer. # vertex_buffer.create_instance_buffer(instance_name="model", # layout_location=self.instance_location_model, # element_data=MATRIX4_IDENTITY) # find skeleton of geometry skeleton = None for skeleton in self.skeletons: if skeleton.name == geometry_data.get('skeleton_name', ''): break # create geometry geometry = Geometry(name=vertex_buffer.name, index=i, vertex_buffer=vertex_buffer, skeleton=skeleton) self.geometries.append(geometry) self.attributes = Attributes()
def get_geometry_data(self): geometry_datas = [] for mesh in self.meshes: positions = [] normals = [] texcoords = [] indices = [] indexMap = {} boundMin = Float3(FLOAT32_MAX, FLOAT32_MAX, FLOAT32_MAX) boundMax = Float3(FLOAT32_MIN, FLOAT32_MIN, FLOAT32_MIN) for n, mesh_indices in enumerate(mesh.indices): # exclude material postionIndicies, normalIndicies, texcoordIndicies = mesh_indices for i in range(len(postionIndicies)): index_key = (postionIndicies[i], normalIndicies[i], texcoordIndicies[i]) if index_key in indexMap: indices.append(indexMap[index_key]) else: indices.append(len(indexMap)) indexMap[index_key] = len(indexMap) positions.append(self.positions[postionIndicies[i]]) normals.append(self.normals[normalIndicies[i]]) texcoords.append(self.texcoords[texcoordIndicies[i]]) # bounding box position = positions[-1] for j in range(3): if boundMin[j] > position[j]: boundMin[j] = position[j] if boundMax[j] < position[j]: boundMax[j] = position[j] if len(positions) == 0: logger.info('%s has a empty mesh. %s' % (self.filename, mesh.name)) continue geometry_data = dict(name=mesh.name, positions=copy.deepcopy(positions), normals=copy.deepcopy(normals), texcoords=copy.deepcopy(texcoords), indices=copy.deepcopy(indices), bound_min=copy.deepcopy(boundMin), bound_max=copy.deepcopy(boundMax), radius=magnitude(boundMax - boundMin)) geometry_datas.append(geometry_data) return geometry_datas
def __init__(self, **texture_data): self.name = texture_data.get('name') self.attachment = False self.image_mode = texture_data.get('image_mode') self.internal_format = texture_data.get('internal_format') self.texture_format = texture_data.get('texture_format') self.sRGB = texture_data.get('sRGB', None) self.multisample_count = 0 if self.internal_format is None and self.image_mode: self.internal_format = get_internal_format(self.image_mode) if self.texture_format is None and self.image_mode: self.texture_format = get_texture_format(self.image_mode) if self.image_mode is None and self.texture_format: self.image_mode = get_image_mode(self.texture_format) # Convert to sRGB if self.sRGB: if self.internal_format == GL_RGB: self.internal_format = GL_SRGB elif self.internal_format == GL_RGBA: self.internal_format = GL_SRGB_ALPHA self.width = texture_data.get('width', 0) self.height = texture_data.get('height', 0) self.depth = max(1, texture_data.get('depth', 1)) self.data_type = texture_data.get('data_type', GL_UNSIGNED_BYTE) self.min_filter = texture_data.get('min_filter', GL_LINEAR_MIPMAP_LINEAR) self.mag_filter = texture_data.get( 'mag_filter', GL_LINEAR) # GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, GL_NEAREST mipmap_filters = (GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_NEAREST_MIPMAP_NEAREST) self.enable_mipmap = self.min_filter in mipmap_filters if self.target == GL_TEXTURE_2D_MULTISAMPLE: self.enable_mipmap = False self.wrap = texture_data.get('wrap', self.default_wrap) # GL_REPEAT, GL_CLAMP self.buffer = None logger.info("Create %s : %s %dx%dx%d %s mipmap(%s)." % (GetClassName(self), self.name, self.width, self.height, self.depth, str(self.internal_format), 'Enable' if self.enable_mipmap else 'Disable')) self.attribute = Attributes()
def addObject(self, **object_data): model = object_data.get('model') if model: object_data['name'] = self.generateObjectName( object_data.get('name', model.name)) objType = GetClassName(model) logger.info("add %s : %s" % (objType, object_data['name'])) if model.mesh and model.mesh.has_bone(): obj_instance = SkeletonActor(**object_data) else: obj_instance = StaticActor(**object_data) # regist self.regist_object(obj_instance) return obj_instance return None
def test_recharge(self, case): logger.info("开始测试:{}".format(case.title)) logger.info("测试入参 ", case.data) print("测试用例标题 ", case.title) print("测试入参 ", case.data) ''' 请求之前,判断是否需要执行SQL ''' if case.sql is not None: sql = eval(case.sql)['sql1'] #转换成字典,使用eval logger.info(sql) member = self.mysql.fetch_one(sql) #返回一个元祖 print("执行sql返回一个字典:{}".format(member)) print("充值前金额:{}", member['LeaveAmount']) before = member['LeaveAmount']
def is_broken_xdg_desktop(pathname): """Returns boolean whether the given XDG desktop entry file is broken. Reference: http://standards.freedesktop.org/desktop-entry-spec/latest/""" config = Common.RawConfigParser() config.read(pathname) if not config.has_section('Desktop Entry'): logger.info( "is_broken_xdg_menu: missing required section 'Desktop Entry': '%s'" % pathname) return True if not config.has_option('Desktop Entry', 'Type'): logger.info( "is_broken_xdg_menu: missing required option 'Type': '%s'" % pathname) return True file_type = config.get('Desktop Entry', 'Type').strip().lower() if 'link' == file_type: if not config.has_option('Desktop Entry', 'URL') and \ not config.has_option('Desktop Entry', 'URL[$e]'): logger.info( "is_broken_xdg_menu: missing required option 'URL': '%s'" % pathname) return True return False if 'mimetype' == file_type: if not config.has_option('Desktop Entry', 'MimeType'): logger.info( "is_broken_xdg_menu: missing required option 'MimeType': '%s'" % pathname) return True mimetype = config.get('Desktop Entry', 'MimeType').strip().lower() if is_unregistered_mime(mimetype): logger.info( "is_broken_xdg_menu: MimeType '%s' not registered '%s'" % (mimetype, pathname)) return True return False if 'application' != file_type: logger.warning("unhandled type '%s': file '%s'" % (file_type, pathname)) return False if __is_broken_xdg_desktop_application(config, pathname): return True return False
class RegisterTest(unittest.TestCase): # contants为文件路径,获取文件的路径,login为excel的sheet excel = do_excel.DoExcel(contants.case_file, 'register') cases = excel.get_cases() #使用DDT的时候不能使用setUP,需要使用@classmethod @classmethod def setUpClass(cls): logger.info('准备测试前置:test_recharge') cls.http_request = HttpRequestSession() cls.mysql = do_mysql.DoMysql() #data可接受字典,元祖,列表等等 @data(*cases) def test_register(self, case): #加入日志 logger.info('开始测试:{}'.format(case.title)) logger.info('测试用例入参:{}'.format(case.data)) print('开始测试:{}'.format(case.title)) print('测试用例入参:{}'.format(case.data)) #判断register_mobile是否存在在case.data中 if case.data.find('register_mobile') > -1: # sql = 'SELECT max(MobilePhone) from future.member' # 查询最大手机号 sql = eval(case.sql)['sql1'] # 转换成字典,使用eval logger.info("注册查询当前最大的手机号:{}".format(sql)) max_phone = self.mysql.fetch_one(sql)['MobilePhone'] # 最大手机号+1 max_phone = int(max_phone) + 1 print('最大手机号码 ', max_phone) #replace方法是替换之后,重新返回新的字符串,重新赋值 case.data = case.data.replace('register_mobile', str(max_phone)) # 替换参数值 # 判断是否需要进行数据库数据验证 if case.sql is not None: # 从case中获取sql,转化成字典,并根据key值获取sql内容 sql = eval(case.sql)['sql1'] # 转换成字典,使用eval logger.info("注册查询当前最大的手机号:{}".format(sql)) member = self.mysql.fetch_one(sql) # 返回一个元祖 print("注册前手机号为:{}".format(member['MobilePhone'])) before = int(member['MobilePhone']) logger.info("注册前手机号为:{}".format(member['MobilePhone']))
def test_register(self, case): #加入日志 logger.info('开始测试:{}'.format(case.title)) logger.info('测试用例入参:{}'.format(case.data)) print('开始测试:{}'.format(case.title)) print('测试用例入参:{}'.format(case.data)) #判断register_mobile是否存在在case.data中 if case.data.find('register_mobile') > -1: # sql = 'SELECT max(MobilePhone) from future.member' # 查询最大手机号 sql = eval(case.sql)['sql1'] # 转换成字典,使用eval logger.info("注册查询当前最大的手机号:{}".format(sql)) max_phone = self.mysql.fetch_one(sql)['MobilePhone'] # 最大手机号+1 max_phone = int(max_phone) + 1 print('最大手机号码 ', max_phone) #replace方法是替换之后,重新返回新的字符串,重新赋值 case.data = case.data.replace('register_mobile', str(max_phone)) # 替换参数值
def test_invest(self, case): logger.info(case.title) print("开始执行测试用例 ", case.title) #请求之前替换参数化的值--替换配置文件online中设置的data的值 case.data = context.replace(case.data) print("替换配置文件完成后,data的值:{}".format(case.data)) #判断是否投资人正常投资,sql是否存在 if case.title == "投资人正常投资": if case.sql is not None: case.sql = context.replace(case.sql) logger.info("替换配置文件完成后,sql的值:{}".format(case.sql)) print("替换配置文件完成后,sql的值:{}".format(case.sql)) #sql1查询用户表,获取LeaveAmount sql1 = eval(case.sql)['sql1'] logger.info(sql1) member = self.mysql.fetch_one(sql1) # 返回一个元祖 before_leave_amount = member['LeaveAmount'] print('before_leave_amount:'.format(before_leave_amount))
def __init__(self, material_name, material_datas={}): self.valid = False logger.info("Load %s material." % material_name) shader_codes = material_datas.get('shader_codes') binary_format = material_datas.get('binary_format') binary_data = material_datas.get('binary_data') uniforms = material_datas.get('uniforms', []) self.material_component_names = [ x[1] for x in material_datas.get('material_components', []) ] self.macros = material_datas.get('macros', OrderedDict()) self.is_translucent = True if 0 < self.macros.get( 'TRANSPARENT_MATERIAL', 0) else False self.name = material_name self.shader_name = material_datas.get('shader_name', '') self.program = -1 self.uniform_buffers = dict( ) # OrderedDict() # Declaration order is important. self.Attributes = Attributes() if binary_format is not None and binary_data is not None: self.compile_from_binary(binary_format, binary_data) self.valid = self.check_validate() and self.check_linked() if not self.valid: logger.error( "%s material has been failed to compile from binary" % self.name) if not self.valid: self.compile_from_source(shader_codes) self.valid = self.check_validate() and self.check_linked() if not self.valid: logger.error( "%s material has been failed to compile from source" % self.name) if self.valid: self.create_uniform_buffers(uniforms)
def new_scene(self): self.clear_scene() # add scene objects self.main_camera = self.addCamera() self.main_light = self.addLight() self.main_light_probe = self.addLightProbe() self.atmosphere = Atmosphere() self.sky = Sky() self.set_current_scene_name( self.resource_manager.sceneLoader.get_new_resource_name( "new_scene")) logger.info("New scene : %s" % self.__current_scene_name) scene_data = self.get_save_data() self.resource_manager.sceneLoader.create_resource( self.__current_scene_name, scene_data) self.post_open_scene()
def __init__(self, core_manager): logger.info("Run game backend : " + self.__class__.__name__) self.running = False self.valid = False self.core_manager = core_manager self.width = 0 self.height = 0 self.full_screen = False self.video_resized = False self.mouse_pos = np.zeros(2) self.mouse_pos_old = np.zeros(2) self.mouse_delta = np.zeros(2) self.wheel_up = False self.wheel_down = False self.mouse_btn_l = False self.mouse_btn_m = False self.mouse_btn_r = False
def initialize(self, core_manager, project_filename=""): self.core_manager = core_manager self.scene_manager = core_manager.scene_manager self.resource_manager = core_manager.resource_manager # default project if project_filename == "": project_filename = self.resource_manager.DefaultProjectFile else: project_filename = os.path.relpath(project_filename, ".") logger.info("initialize %s : %s" % (GetClassName(self), project_filename)) try: self.next_open_project_filename = "" self.project_name = os.path.splitext( os.path.split(project_filename)[1])[0] self.project_dir = os.path.split(project_filename)[0] self.project_filename = project_filename self.config = Config(project_filename, log_level) # set default config self.config.setDefaultValue("Screen", "size", [1280, 720]) self.config.setDefaultValue("Screen", "full_screen", False) meter_per_unit = 1.0 # 1 unit = 1 m self.config.setDefaultValue("Camera", "meter_per_unit", meter_per_unit) self.config.setDefaultValue("Camera", "near", 0.1 / meter_per_unit) # 10 cm self.config.setDefaultValue("Camera", "far", 2000.0 / meter_per_unit) # 2 km self.config.setDefaultValue("Camera", "fov", 60) self.config.setDefaultValue("Camera", "move_speed", meter_per_unit) self.config.setDefaultValue("Camera", "pan_speed", meter_per_unit) self.config.setDefaultValue("Camera", "rotation_speed", 0.3) except: logger.info("Cannot open %s : %s" % (GetClassName(self), project_filename)) return False return True
def exit(self): # send a message to close ui if self.uiCmdQueue: self.uiCmdQueue.put(COMMAND.CLOSE_UI) # write config if self.valid: self.config.setValue("Project", "recent", self.projectManager.project_filename) self.config.setValue("Project", "game_backend", self.last_game_backend) self.config.save() # save config # save project self.projectManager.close_project() self.renderer.close() self.resource_manager.close() self.renderer.destroyScreen() self.game_backend.quit() logger.info("Process Stop : %s" % GetClassName(self)) # process stop
def __is_broken_xdg_desktop_application(config, desktop_pathname): """Returns boolean whether application deskop entry file is broken""" if not config.has_option('Desktop Entry', 'Exec'): logger.info( "is_broken_xdg_menu: missing required option 'Exec': '%s'" % desktop_pathname) return True exe = config.get('Desktop Entry', 'Exec').split(" ")[0] if not FileUtilities.exe_exists(exe): logger.info("is_broken_xdg_menu: executable '%s' does not exist '%s'" % (exe, desktop_pathname)) return True if 'env' == exe: # Wine v1.0 creates .desktop files like this # Exec=env WINEPREFIX="/home/z/.wine" wine "C:\\Program # Files\\foo\\foo.exe" execs = shlex.split(config.get('Desktop Entry', 'Exec')) wineprefix = None del execs[0] while True: if 0 <= execs[0].find("="): (name, value) = execs[0].split("=") if 'WINEPREFIX' == name: wineprefix = value del execs[0] else: break if not FileUtilities.exe_exists(execs[0]): logger.info( "is_broken_xdg_menu: executable '%s' does not exist '%s'" % (execs[0], desktop_pathname)) return True # check the Windows executable exists if wineprefix: windows_exe = wine_to_linux_path(wineprefix, execs[1]) if not os.path.exists(windows_exe): logger.info( "is_broken_xdg_menu: Windows executable '%s' does not exist '%s'" % (windows_exe, desktop_pathname)) return True return False
def delete(self): logger.info("Delete %s : %s" % (GetClassName(self), self.name)) glDeleteTextures([ self.buffer, ]) self.buffer = -1
def tearDownClass(cls): logger.info('测试后置处理') cls.http_request.close() cls.mysql.close()
def setUpClass(cls): logger.info('准备测试前置:test_recharge') cls.http_request = HttpRequestSession() cls.mysql = do_mysql.DoMysql()
# 从case中获取sql,转化成字典,并根据key值获取sql内容 sql = eval(case.sql)['sql1'] # 转换成字典,使用eval logger.info("注册查询当前最大的手机号:{}".format(sql)) member = self.mysql.fetch_one(sql) # 返回一个元祖 print("注册前手机号为:{}".format(member['MobilePhone'])) before = int(member['MobilePhone']) logger.info("注册前手机号为:{}".format(member['MobilePhone'])) resp = self.http_request.request(case.method, case.url, case.data) try: self.assertEqual(case.expected, resp.text) self.excel.write_result(case.case_id + 1, resp.text, 'PASS') if case.sql is not None: sql = eval(case.sql)['sql1'] logger.info("注册查询当前最大的手机号:{}".format(sql)) member = self.mysql.fetch_one(sql) # print("注册成功后的手机号为:{}".format(member['MobilePhone'])) after = int(member['MobilePhone']) self.assertEqual(before + 1, after) logger.info("注册成功后的手机号为:{}".format(member['MobilePhone'])) except AssertionError as e: self.excel.write_result(case.case_id + 1, resp.text, 'FAILED') logger.info("ERROR:{}".format(e)) raise e logger.info('结束测试:{}'.format(case.title)) @classmethod def tearDownClass(cls):
def initialize(self, core_manager): logger.info("initialize " + GetClassName(self)) self.core_manager = core_manager self.renderer = core_manager.renderer self.clear()
def setUpClass(cls): logger.info("TEST CASE START : InvestTest") cls.http_request = HttpRequestSession() cls.mysql = do_mysql.DoMysql()
class RechargeTest(unittest.TestCase): # contants为文件路径,获取文件的路径,recharge为excel的sheet excel = do_excel.DoExcel(contants.case_file, 'recharge') cases = excel.get_cases() ''' #使用DDT的时候不能使用setUP,需要使用@classmethod #使用classmethod是为了在setUpClass开一次 ''' @classmethod def setUpClass(cls): logger.info('准备测试前置:test_recharge') cls.http_request = HttpRequestSession() cls.mysql = do_mysql.DoMysql() ''' #data可接受字典,元祖,列表等等 ''' @data(*cases) def test_recharge(self, case): logger.info("开始测试:{}".format(case.title)) logger.info("测试入参 ", case.data) print("测试用例标题 ", case.title) print("测试入参 ", case.data) ''' 请求之前,判断是否需要执行SQL ''' if case.sql is not None: sql = eval(case.sql)['sql1'] #转换成字典,使用eval logger.info(sql) member = self.mysql.fetch_one(sql) #返回一个元祖 print("执行sql返回一个字典:{}".format(member)) print("充值前金额:{}", member['LeaveAmount']) before = member['LeaveAmount'] #调用http_request中的request方法,返回结果保存在resp中 resp = self.http_request.request(case.method, case.url, case.data) #调用json方法,转成json串,拿到json【字典】中的key:code actual_code = resp.json()['code'] try: #调用asserEqual,进行断言,判断case中expected和获取的json中code的值是否一致 self.assertEqual(str(case.expected), actual_code) #调用excel中的write_result方法,写入数据 self.excel.write_result(case.case_id + 1, resp.text, 'PASS') if case.sql is not None: sql = eval(case.sql)['sql1'] logger.info(sql) member = self.mysql.fetch_one(sql) # 返回一个元祖 print("充值后金额:{}".format(member['LeaveAmount'])) after = member['LeaveAmount'] recharge_amount = int(eval(case.data)['amount']) # 充值金额 self.assertEqual(before + recharge_amount, after) except AssertionError as e: # self.excel.write_result(case.case_id + 1, resp.text, 'FAILED') logger.error('ERROR:{}'.format(e)) raise e logger.info('结束测试:{}'.format(case.title))