Exemple #1
0
class Wework(BaseApi):
    """
    获取企业微信的access_token,后续应该得写在BaseApi的父类,这个类没啥必要了

    CORP_ID:企业微信的企业id
    """
    # 通过配置文件获取企业微信的id
    CORP_ID = cf.get_key("wwork", "corp_id")

    def get_token(self, secret):
        """
        获取access_token,不同的应用的秘钥,会产生不同的access_token,所以就封装起来了
        :param secret: 企业微信不同也应用的密码
        :return: access_token的值
        """
        data = {
            "method": "GET",
            "url": f"https://qyapi.weixin.qq.com/cgi-bin/gettoken",
            "params": f"corpid={self.CORP_ID}&corpsecret={secret}"
        }
        # 使用send_api,传入data,相当于使用了requests了
        res = self.send_api(data)
        # 获取access_token
        token = res["access_token"]
        return token
Exemple #2
0
class Department(BaseApi):
    base_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    ip = cf.get_key("env", "formal_ip")

    def get_depart(self, id=None):
        p_data = {"ip": self.ip, "token": token, "id": id}
        res = self.send_api_data("data/department/department_api.yml", p_data,
                                 "get")
        return res
Exemple #3
0
class Wework(BaseApi):
    # 通过配置文件获取企业微信的id
    corpid = cf.get_key("wwork", "corp_id")

    # 获取access_token,不同的应用的秘钥,会产生不同的access_token,所以就封装起来了
    def get_token(self, secret):
        data = {
            "method": "GET",
            "url": f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?",
            "params": f"corpid={self.corpid}&corpsecret={secret}"
        }
        # 使用send_api,传入data,相当于使用了requests了
        res = self.send_api(data)
        # 获取access_token
        token = res["access_token"]
        return token
Exemple #4
0
    def set_file(self):
        # 日期:创造Log_2020-12-03.log文件
        a = self.log_name+"_"+str(datetime.date.today()) + ".logs"
        b = os.path.join(self.BASE_PATH,"logs",a)

        # 通过配置文件,获取log是w模式还是a的追加模式
        file_mode=cf.get_key("logs","file_mode")

        # 文件处理器,文件名为demo.logs
        filehandle = logging.FileHandler(filename=b,mode=file_mode)
        # 默认等级为INFO
        filehandle.setLevel(logging.INFO)
        # 处理器添加格式,这里都添加同一个
        filehandle.setFormatter(self.formatter)
        # 记录器添加处理器,就拥有了屏幕输出的和文件输出的日志了
        self.logger.addHandler(filehandle)
Exemple #5
0
 def __init__(self):
     """
     初始化mysql的conn对家,连接数据库
     """
     # 通过配置文件获取数据库的host,port,username,password,charset,database
     host = cf.get_key("mysql", "host")
     # 从配置文件获取的值是str,需要转化成int
     port = int(cf.get_key("mysql", "port"))
     user = cf.get_key("mysql", "user")
     password = cf.get_key("mysql", "password")
     charset = cf.get_key("mysql", "charset")
     database = cf.get_key("mysql", "database")
     # 当无法连接数据库,走异常处理处理
     try:
         self.conn = pymysql.connect(host=host,
                                     port=port,
                                     user=user,
                                     password=password,
                                     charset=charset,
                                     database=database)
     except Exception as e:
         log.error(f"无法登陆数据库,错误原因:{e}")
class WCalendar(BaseApi):
    """
    企业微信日程中的日历模块的API类

    secret:日历的秘钥
    token:日历的token
    yml_api_path: yml api数据的相对路径
    """

    # 通过配置文件获取日历的secret,token只是为了测试方法,其实不应该存在的
    secret = cf.get_key("wwork", "schedule_secret")
    token = Wework().get_token(secret)
    # yml api数据的相对路径
    yml_api_path = "data/schedule/calendar/calendar_api.yml"

    # 不用yml文件保存cal_id的数据了,放在数据库好啦
    # cal_id_path="data/schedule/calendar/cal_id.yml"

    def get_cal_id_list(self):
        """
        通过数据库,获取日历id的值,日历id的值无法通过接口获取,所以就保存在数据库中
        :return: 返回全部的日历id的列表
        """
        # 执行sql语句获取日历id的元祖
        cal_id_tuple = sql.select("select cal_id from cal_id")
        # 把元祖转化成列表
        cal_id_list = [i[0] for i in cal_id_tuple]
        return cal_id_list

    def add_calendar(self, token, organizer, readonly, set_as_default, summary, color, description):
        """
        添加日历
        :param token: access_token的值
        :param organizer: 请求参数的值
        :param readonly: 请求参数的值
        :param set_as_default: 请求参数的值
        :param summary: 请求参数的值
        :param color: 请求参数的值
        :param description: 请求参数的值
        :return: 返回响应体
        """
        # Template模板需要二次改变的值
        p_data = {"ip": self.ip, "token": token, "organizer": organizer, "readonly": readonly,
                  "set_as_default": set_as_default, "summary": summary, "color": color, "description": description}
        res = self.send_api_data(self.yml_api_path, p_data, "add")
        try:
            cal_id = res["cal_id"]
            # 当cal_id获取到了,就把cal_id放到数据库中
            sql.insert(f"insert into cal_id(userid,cal_id) values('{organizer}','{cal_id}')")
        except KeyError:
            log.error(f"响应不正确,无法插入数据")

        # 用yml文件保存数据的方法不要了
        # try:
        #     cal_id=res["cal_id"]
        #     cal_id_list=self.load_yaml(self.cal_id_path)
        #     cal_id_list.append(cal_id)
        #     cal_id_list=list(filter(None,cal_id_list))
        #     self.save_yaml(self.cal_id_path,cal_id_list)
        # except:
        #     log.info(f"无法获取到cal_id")
        return res

    def get_calendar(self, token, index=None):
        """
        获取日历信息
        :param token: 日历的token值
        :param index: 在数据库获取第几个id值
        :return: 返回响应体
        """
        # 解决index存在的时候,传的cal_id_list是一个列表
        cal_id_list = []
        # 从数据库获取cal_id_list,才能查询日历
        if index is None:
            cal_id_list = self.get_cal_id_list()
        else:
            cal_id_list.append(self.get_cal_id_list()[index])
        p_data = {"ip": self.ip, "token": token, "cal_id_list": cal_id_list}
        res = self.send_api_data(self.yml_api_path, p_data, "get")
        return res

    def delete_calendar(self, token, index):
        """
        删除日历
        :param token: 日历的token值
        :param index: 在数据库获取第几个id值
        :return: 返回响应体
        """
        # 从数据库获取cal_id_list
        cal_id = self.get_cal_id_list()[index]
        p_data = {"ip": self.ip, "token": token, "cal_id": cal_id}
        res = self.send_api_data(self.yml_api_path, p_data, "delete")
        # 当删除api成功时,同步从数据库中删除cal_id
        if res["errcode"] == 0:
            sql.delete(f"delete from cal_id where cal_id='{cal_id}'")
        else:
            log.info("日历删除请求有误,数据库没有删除cal_id")
        return res

    def edit_calendar(self, token, index, readonly, summary, color, description):
        """
        编辑日历
        :param token: 日历的token值
        :param index: 请求参数的值
        :param readonly: 请求参数的值
        :param summary: 请求参数的值
        :param color: 请求参数的值
        :param description: 请求参数的值
        :return: 返回响应体
        """
        # 从数据库获取cal_id_list
        cal_id = self.get_cal_id_list()[index]
        p_data = {"ip": self.ip, "token": token, "cal_id": cal_id, "readonly": readonly, "summary": summary,
                  "color": color, "description": description}
        res = self.send_api_data(self.yml_api_path, p_data, "edit")
        return res
class TestMember():
    """
    联系人的测试类
    1.参数化存放在特定的yml文件中,用三级目录管理用例、参数数据和ids的数据
    2.token值并没有使用conftest的fixture,而是在测试类中获取,效率不高
    3.并未对token的值做参数化
    4.critical的用例等级为完整测试,blocker等级为冒烟测试
    5.每个用例都配合fixture,完成了不同的前置和后置,实现了不同用例互不干扰的状态
    """
    @classmethod
    def get_token(cls, token):
        return token

    # 通过配置文件获取联系人的secret
    contact_secret = cf.get_key("wwork", "contact_secret")
    # 获取access_token
    token = Wework().get_token(contact_secret)
    # 初始化member的api对象
    member = Member()

    # # 比如在类中,怎么才能导入这个conftest的token
    # access_token=token
    '''
    这样获取数据的方法,要读取两次文件,速度太慢了
    add_data = member.load_yaml("data/member/member_para_data.yml")['add']['data']
    add_ids = member.load_yaml("data/member/member_para_data.yml")['add']['ids']
    '''
    # 参数化的数据
    para_data = member.load_yaml("data/member/member_para_data.yml")

    # 删除用例的参数化数据和ids标题数据
    delete_data = para_data['delete']['data']
    delete_ids = para_data['delete']['ids']
    # 删除用例的参数化数据和ids标题数据
    multi_delete_data = para_data['multi_delete']['data']
    multi_delete_ids = para_data['multi_delete']['ids']
    # 删除用例的参数化数据和ids标题数据
    add_data = para_data['add']['data']
    add_ids = para_data['add']['ids']
    # 删除用例的参数化数据和ids标题数据
    edit_data = para_data['edit']['data']
    edit_ids = para_data['edit']['ids']
    # 删除用例的参数化数据和ids标题数据
    get_data = para_data['get']['data']
    get_ids = para_data['get']['ids']
    # 删除用例的参数化数据和ids标题数据
    active_data = para_data['active']['data']
    active_ids = para_data['active']['ids']
    # 删除用例的参数化数据和ids标题数据
    qr_data = para_data['qr']['data']
    qr_ids = para_data['qr']['ids']
    # 删除用例的参数化数据和ids标题数据
    depart_simple_data = para_data['depart_simple']['data']
    depart_simple_ids = para_data['depart_simple']['ids']
    # 删除用例的参数化数据和ids标题数据
    depart_explicit_data = para_data['depart_explicit']['data']
    depart_explicit_ids = para_data['depart_explicit']['ids']

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("增加联系人")
    @pytest.mark.parametrize(("userid,name,mobile,errcode,errmsg"),
                             add_data,
                             ids=add_ids)
    def test01_add_member(self, userid, name, mobile, errcode, errmsg, add):
        log.info(f"-------开始测试增加成员-------")
        res = self.member.add_member(self.token, userid, name, mobile)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("获得联系人信息")
    @pytest.mark.parametrize(("userid,errcode,errmsg"), get_data, ids=get_ids)
    def test02_get_member(self, userid, errcode, errmsg, get):
        log.info("-------开始测试获取成员-------")
        res = self.member.get_member_info(self.token, userid)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("删除联系人")
    @pytest.mark.parametrize(("userid,errcode,errmsg"),
                             delete_data,
                             ids=delete_ids)
    def test04_delete_member(self, userid, errcode, errmsg, delete):
        log.info("-------开始测试获取成员-------")
        res = self.member.delete_member(self.token, userid)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("批量删除联系人")
    @pytest.mark.parametrize(("userid_list,errcode,errmsg"),
                             multi_delete_data,
                             ids=multi_delete_ids)
    def test05_multi_delete_member(self, userid_list, errcode, errmsg,
                                   multi_delete):
        log.info("-------开始批量删除获取成员-------")
        res = self.member.multi_delete_member(self.token, userid_list)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("编辑联系人")
    @pytest.mark.parametrize(("userid,name,mobile,errcode,errmsg"),
                             edit_data,
                             ids=edit_ids)
    def test03_edit_member(self, userid, name, mobile, errcode, errmsg, edit):
        log.info("-------开始修改获取成员-------")
        res = self.member.edit_member(self.token, userid, name, mobile)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("查看企业微信活跃度")
    @pytest.mark.parametrize(("date,errcode,errmsg"),
                             active_data,
                             ids=active_ids)
    def test_active_stat(self, date, errcode, errmsg):
        log.info("-------开始查看企业微信活跃度-------")
        res = self.member.get_active_stat(self.token, date)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("增加联系人")
    @pytest.mark.parametrize(("size,errcode,errmsg"), qr_data, ids=qr_ids)
    def test_get_invite_qr(self, size, errcode, errmsg):
        log.info("-------开始获取企业微信二维码-------")
        res = self.member.get_invite_qr(self.token, size)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("查看部门联系人的简单信息")
    @pytest.mark.parametrize(("department_id,fetch_child,errcode,errmsg"),
                             depart_simple_data,
                             ids=depart_simple_ids)
    def test_get_depart_member(self, department_id, fetch_child, errcode,
                               errmsg):
        log.info("-------开始获取部门成员简单的信息-------")
        res = self.member.get_depart_member(self.token, department_id,
                                            fetch_child)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("查看部门联系人的复杂信息")
    @pytest.mark.parametrize(("department_id,fetch_child,errcode,errmsg"),
                             depart_explicit_data,
                             ids=depart_explicit_ids)
    def test_get_depart_member_explict(self, department_id, fetch_child,
                                       errcode, errmsg):
        log.info("-------开始部门成员详细信息-------")
        res = self.member.get_depart_member_explicit(self.token, department_id,
                                                     fetch_child)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.BLOCKER)
    @allure.story("增加联系人")
    @pytest.mark.smoke
    def test_all_smoke_member(self, test_all_pre_data):
        add_res = self.member.add_member(self.token, "tong1234", "tong1234",
                                         "13172771165")
        edit_res = self.member.edit_member(self.token, "tong1234", "tong1234",
                                           "13172771165")
        del_res = self.member.delete_member(self.token, "tong1234")
        multi_del_res = self.member.multi_delete_member(
            self.token, ["tongtong1", "tongtong2", "tongtong3"])
        qr_res = self.member.get_invite_qr(self.token, 1)
        active_res = self.member.get_active_stat(self.token, "2020-10-10")
        depart_res = self.member.get_depart_member(self.token, "1", "1")
        depart_res_e = self.member.get_depart_member_explicit(
            self.token, "1", "1")
        assert add_res["errcode"] == 0
        assert edit_res["errcode"] == 0
        assert del_res["errcode"] == 0
        assert multi_del_res["errcode"] == 0
        assert qr_res["errcode"] == 0
        assert active_res["errcode"] == 40058
        assert depart_res["errcode"] == 0
        assert depart_res_e["errcode"] == 0
        log.info("finish")
Exemple #8
0
import os
from api.base_api import BaseApi
from api.wework import Wework
from common.config import cf
from common.get_log import log

secret = cf.get_key("wwork", "contact_secret")
token = Wework().get_token(secret)


class Department(BaseApi):
    base_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
    ip = cf.get_key("env", "formal_ip")

    def get_depart(self, id=None):
        p_data = {"ip": self.ip, "token": token, "id": id}
        res = self.send_api_data("data/department/department_api.yml", p_data,
                                 "get")
        return res


if __name__ == "__main__":
    a = Department()
    print(a.get_depart())
Exemple #9
0
class BaseApi:
    """
    实现了所有公共类API的需要的东西,是其他API的父类

    ip:测试环境的ip地址
    Base_Path:项目的根路径
    """

    # 通过配置文件获取测试的环境的ip地址
    ip = cf.get_key("env", "formal_ip")
    Base_Path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

    def send_api(self, req: dict):
        """
        封装requests代码,替代requests.request方法
        :param req: 传入请求的字典数据,包括method,url,params,json
        :return: 响应体
        """
        """
        req传入的数据类型如下
        req={
            "method":"GET",
            "url":f"https://qyapi.weixin.qq.com/cgi-bin/gettoken?",
            "params":f"corpid={self.corpid}&corpsecret={secret}"
        }
        request的参数接收method,url,params,data,json
        把这些参数都写在一个字典里面,**req就可以解包
        变成method="get",url="http://xxx",符合request传参的需求
        """

        res = requests.request(**req).json()
        return res

    @classmethod
    def get_time(cls, date):
        """
        时间字符串转化成时间戳,格式:2013-10-10 23:40:00,转化成1605021256的时间戳
        :param date: 2013-10-10 23:40:00的时间格式
        :return: 返回时间戳1605021256
        """
        # 先转换成时间格式对象,再转化成时间戳
        time_strp = time.strptime(date, "%Y-%m-%d %H:%M:%S")
        time_stamp = int(time.mktime(time_strp))
        return time_stamp

    @classmethod
    def jsonpath(cls, json, expr):
        """
        优化jsonpath代码,其他类就不用from jsonpath improt jsonpath了
        :param json: 传入json格式,发现json或者字典都ok也
        :param expr: 要获取json内容的表达式
        :return: 返回想要的字符串
        """
        return jsonpath(json, expr)

    @classmethod
    def load_yaml(cls, path, sub=None):
        """
        封装yaml读取的代码,通过路径直接读取yml文件并转化成python数据类型
        :param path: yml文件的相对路径
        :param sub: 读取yml文件的二级数据目录,默认为None
        :return: 返回yml文件的python数据
        """
        # 链接根路径和yml文件的相对路径,简化文件路径
        path = os.path.join(cls.Base_Path, path)
        with open(path, encoding="utf-8") as f:
            # 不写sub就获取yml的所有内容,写就获取yml的二级数据目录
            if sub is None:
                return yaml.safe_load(f)
            else:
                return yaml.safe_load(f)[sub]

    @classmethod
    def save_yaml(cls, path, data):
        """
        封装yaml写入的代码
        :param path: yml文件的相对路径
        :param data: python的数据
        """
        # 链接根路径和yml文件的相对路径,简化文件路径
        path = os.path.join(cls.Base_Path, path)
        with open(
                path,
                "r+",
                encoding="utf-8",
        ) as f:
            yaml.safe_dump(data, f)

    @classmethod
    def template(cls, path, data, sub=None):
        """
        使用模板技术,把yml文件中的变量进行二次转化,是本框架的yml文件的技术基础
        :param path: 模板技术输入yml文件相对路径
        :param data: data是需要修改的模板变量的字典类型
        :param sub: sub是对yml的数据进行二次提取,等于是一个大字典,再提取下一层的小字典,为了让一个yml文件可以有多个接口数据
        :return:
        """
        with open(path, encoding="utf-8") as f:
            if sub is None:
                '''
                不需要对数据进行二次提取,Template(f.read()).substitute(data)先替换变量
                yaml.safe_load把yml格式的字符串变成dict类型返回
                '''
                return yaml.safe_load(Template(f.read()).substitute(data))
            else:
                '''
                由于Template需要替换全部的变量,有漏的就会报错,先写Template(f.read()).substitute(data)
                就会报错,data只对sub下一层的数据改,并没有改其他层的数据,肯定会报错
                需要先yaml.safe_load(f)[sub]提取到下一层的数据,但由于是dict
                要通过yaml.dump转化成yml格式的字符串,经过Template来改变变量,最后在yaml.safe_load转化成dict
                '''
                return yaml.safe_load(
                    Template(yaml.dump(
                        yaml.safe_load(f)[sub])).substitute(data))
                # 错误的写法:return yaml.safe_load(Template(f.read()).substitute(data))

    #
    def send_api_data(self, path, p_data, sub):
        """
        1.进一步优化封装请求,是本框架的第二个核心技术要点
        2.解决了如何非必填字段的问题,接口测试的非必填字段,只需要传入None值就好
        2.1 本方法就是解决如何传入None的问题
        :param path: 存放yml的api数据的相对路径
        :param p_data: Template模板里面,二次转化的数据
        :param sub: yml的二级数据目录,区别同一个api类中不同的api方法,比如add,delete
        :return: 返回请求体的字典类型
        """
        # 链接根路径和yml文件的相对路径,简化文件路径
        path = os.path.join(self.Base_Path, path)
        # 获取请求数据
        data: dict = self.template(path, p_data, sub)
        log.info(f"api模板改变的参数为:{p_data}")
        # 由于Template转化的数据都是字符串,None也会变成'None',通过下面的方法解决这个问题
        # 防止有些请求没有请求体的,不然就报错了
        try:
            for i in data['json'].keys():
                if data['json'][i] == 'None':
                    data['json'][i] = None
        except:
            pass
        log.info(f"修改后的请求为:{data}")
        res = self.send_api(data)
        log.info((f"响应为:{res}"))
        return res
Exemple #10
0
class WSchedule(BaseApi):
    """
    企业微信日程中的日程模块的API类

    secret:日历的秘钥
    token:日历的token
    yml_api_path: yml api数据的相对路径
    """

    # 通过配置文件获取日历的secret,token只是为了测试方法,其实不应该存在的
    secret = cf.get_key("wwork", "schedule_secret")
    token = Wework().get_token(secret)
    # yml api数据的相对路径
    data_path = "data/schedule/schedule/schedule_api.yml"

    def get_schedule_id_list(self):
        """
        通过数据库,获取日程id的值,日程id的值无法通过接口获取,所以就保存在数据库中
        :return: 返回全部的日历程id的列表
        """
        # 执行sql语句获取日历id的元祖
        schedule_id_list = sql.select("select schedule_id from schedule_id")
        # 把元祖转化成列表
        schedule_id_list = [i[0] for i in schedule_id_list]
        return schedule_id_list

    def add_schedule(self, token, organizer, start_time, end_time, userid,
                     summary, description, location):
        """
        增加日程
        :param token: access_token的值
        :param organizer: 请求参数的值
        :param start_time: 请求参数的值
        :param end_time: 请求参数的值
        :param userid: 请求参数的值
        :param summary: 请求参数的值
        :param description: 请求参数的值
        :param location: 请求参数的值
        :return: 返回响应体
        """
        # 时间传入时间戳,get_time可以将时间字符串转化成时间戳,自己封装的
        start_time = self.get_time(start_time)
        end_time = self.get_time(end_time)
        # Template模板需要二次改变的值
        p_data = {
            "ip": self.ip,
            "token": token,
            "organizer": organizer,
            "start_time": start_time,
            "end_time": end_time,
            "userid": userid,
            "summary": summary,
            "description": description,
            "location": location
        }
        res = self.send_api_data(self.data_path, p_data, "add")
        try:
            schedule_id = res["schedule_id"]
            # 当cal_id获取到了,就把schedule_id放到数据库中
            sql.insert(
                f"insert into schedule_id(userid,schedule_id) values('{organizer}','{schedule_id}')"
            )
        except KeyError as e:
            log.error("响应不正确,无法插入数据")
        return res

    def delete_schedule(self, token, index):
        """
        删除日程
        :param token: 日历的token值
        :param index: 在数据库获取第几个id值
        :return: 返回响应体
        """
        # 从数据库获取schedule_id
        schedule_id = self.get_schedule_id_list()[index]
        p_data = {"ip": self.ip, "token": token, "schedule_id": schedule_id}
        res = self.send_api_data(self.data_path, p_data, "delete")
        # 当删除api成功时,同步从数据库中删除schedule_id
        if res["errcode"] == 0:
            sql.delete(
                f"delete from schedule_id where schedule_id='{schedule_id}'")
        else:
            log.info("删除请求失败,无法删除schedule_id")
        return res

    def get_schedule(self, token, index=None):
        """
        获取日程信息
        :param token: 日程的token值
        :param index: 在数据库获取第几个id值
        :return: 返回响应体
        """
        # 解决index存在的时候,传的schedule_id_list不是一个列表
        schedule_id_list = []
        # 从数据库获取schedule_id_list,才能查询日历
        if index is None:
            schedule_id_list = self.get_schedule_id_list()
        else:
            schedule_id_list.append(self.get_schedule_id_list()[index])
        p_data = {
            "ip": self.ip,
            "token": token,
            "schedule_id_list": schedule_id_list
        }
        res = self.send_api_data(self.data_path, p_data, "get")
        return res

    def edit_schedule(self, token, organizer, index, start_time, end_time,
                      userid, summary, description, location):
        """

        :param token: 日程的token值
        :param organizer: 请求参数的值
        :param index: 请求参数的值
        :param start_time: 请求参数的值
        :param end_time: 请求参数的值
        :param userid: 请求参数的值
        :param summary: 请求参数的值
        :param description: 请求参数的值
        :param location: 请求参数的值
        :return:
        """
        # 从数据库获取schedule_id
        schedule_id = self.get_schedule_id_list()[index]
        start_time = self.get_time(start_time)
        end_time = self.get_time(end_time)
        p_data = {
            "ip": self.ip,
            "token": token,
            "organizer": organizer,
            "schedule_id": schedule_id,
            "start_time": start_time,
            "end_time": end_time,
            "userid": userid,
            "summary": summary,
            "description": description,
            "location": location
        }
        res = self.send_api_data(self.data_path, p_data, "edit")
        return res
class Member(BaseApi):
    """
    通讯录的api类,比较low的代码展示,其他api类在不断完善中

    env_ip:测试环境的ip,都可以放到父类
    BASE_PATH:根路径,都可以放到父类
    """
    # 定义不同测试、生产环境的ip,通过配置文件获取
    # 但是这里并没有用到,是比较老的api代码了
    env_ip = cf.get_key("env", "formal_ip")
    # 定义项目的绝对根路径
    BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

    #
    def send_api_data(self, p_data, path):
        """
        封装从yml拿数据,并改变替换yml原本的$变量的数据
        :param p_data: Template二次转化的变量数据
        :param path: yml_api的路径
        :return:
        """
        # 打印传入template要改变的$变量值
        log.info(f"template传入的p_data:{p_data}")
        # 读取yml文件的路径
        data_path = os.path.join(self.BASE_PATH, path)
        # 改变yml文件的$变量值
        data = self.template(data_path, p_data)
        log.info(f"请求的所有参数:{data}")
        # 获取响应体
        res = self.send_api(data)
        return res

    def add_member(self, token, userid, name, mobile):
        """
        增加联系人,这里代码没有封装,看起来很乱
        :param token: token值
        :param userid: 请求参数的值
        :param name: 请求参数的值
        :param mobile: 请求参数的值
        :return: 返回响应体
        """
        # Template模板二次修改的值,p_data
        p_data = {
            "token": token,
            "name": name,
            "userid": userid,
            "mobile": mobile
        }
        # 合并yml_api的文件路径
        data_path = os.path.join(self.BASE_PATH, "data/member/add_member.yml")
        # 通过模板技术获取更改后的请求数据
        data = self.template(data_path, p_data)
        # log日志打印请求体
        log.info(data)
        # 发送封装requests的请求,获取响应值
        res = self.send_api(data)
        return res

    def get_invite_qr(self, token, size_type):
        """
        获取企业微信邀请二维码,代码进行了优化缩减,使用了send_api_data进一个封装代码
        :param token: token值
        :param size_type: 二维码尺寸大小
        :return: 返回响应体
        """
        p_data = {"token": token, "size_type": size_type}
        res = self.send_api_data(p_data, "data/member/get_invite_qr.yml")
        """
        这四行代码用上面的两行代码搞定了
        p_data = {"token": token, "size_type": size_type}
        data_path = os.path.join(self.BASE_PATH, "data/member/get_invite_qr.yml")
        data = self.base.template(data_path, p_data)
        res = self.send_api(data)
        """
        return res

    # 获取企业微信活跃数
    def get_active_stat(self, token, date):
        p_data = {"ip": self.env_ip, "token": token, "date": date}
        res = self.send_api_data(p_data, "data/member/get_active_stat.yml")
        return res

    # 获取企业微信用户数
    def get_member_info(self, token, userid):
        p_data = {"token": token, "userid": userid}
        data_path = os.path.join(self.BASE_PATH, "data/member/get_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    # 编辑联系人
    def edit_member(self, token, userid, name, mobile):
        p_data = {
            "token": token,
            "name": name,
            "userid": userid,
            "mobile": mobile
        }
        data_path = os.path.join(self.BASE_PATH, "data/member/edit_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    # 删除联系人
    def delete_member(self, token, userid):
        p_data = {"token": token, "userid": userid}
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/delete_member.yml")
        data = self.template(data_path, p_data)
        log.info(f"请求的参数:{data}")
        res = self.send_api(data)
        return res

    # 批量删除联系人
    def multi_delete_member(self, token, uesrid_list):
        p_data = {"token": token, "userid_list": uesrid_list}
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/multi_delete_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    # 获取部门的联系人信息
    def get_depart_member(self, token, department_id, fetch_child):
        p_data = {
            "token": token,
            "department_id": department_id,
            "fetch_child": fetch_child
        }
        log.info(p_data)
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/get_depart_member.yml")
        data = self.template(data_path, p_data)
        log.info(data)
        res = self.send_api(data)
        return res

    # 获取部门详细的联系人信息
    def get_depart_member_explicit(self, token, department_id, fetch_child):
        p_data = {
            "token": token,
            "department_id": department_id,
            "fetch_child": fetch_child
        }
        log.info(p_data)
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/get_depart_member_explicit.yml")
        data = self.template(data_path, p_data)
        log.info(data)
        res = self.send_api(data)
        return res
Exemple #12
0
def token():
    secret = cf.get_key("wwork", "meeting_room_secret")
    token = Wework().get_token(secret)
    return token
def schedule_token():
    schedule_secret = cf.get_key("wwork", "schedule_secret")
    token = Wework().get_token(schedule_secret)
    return token
class TestMember():
    # 通过配置文件获取联系人的secret
    contact_secret = cf.get_key("wwork", "contact_secret")
    # 获取access_token
    token = Wework().get_token(contact_secret)
    # 初始化member的api对象
    member = Member()
    '''
    这样获取数据的方法,要读取两次文件,速度太慢了
    add_data = member.load_yaml("data/member/member_para_data.yml")['add']['data']
    add_ids = member.load_yaml("data/member/member_para_data.yml")['add']['ids']
    '''
    # 参数化的数据
    para_data = member.load_yaml("data/member/member_para_data.yml")

    # 删除用例的参数化数据和ids标题数据
    delete_data = para_data['delete']['data']
    delete_ids = para_data['delete']['ids']
    # 删除用例的参数化数据和ids标题数据
    multi_delete_data = para_data['multi_delete']['data']
    multi_delete_ids = para_data['multi_delete']['ids']
    # 删除用例的参数化数据和ids标题数据
    add_data = para_data['add']['data']
    add_ids = para_data['add']['ids']
    # 删除用例的参数化数据和ids标题数据
    edit_data = para_data['edit']['data']
    edit_ids = para_data['edit']['ids']
    # 删除用例的参数化数据和ids标题数据
    get_data = para_data['get']['data']
    get_ids = para_data['get']['ids']
    # 删除用例的参数化数据和ids标题数据
    active_data = para_data['active']['data']
    active_ids = para_data['active']['ids']
    # 删除用例的参数化数据和ids标题数据
    qr_data = para_data['qr']['data']
    qr_ids = para_data['qr']['ids']
    # 删除用例的参数化数据和ids标题数据
    depart_simple_data = para_data['depart_simple']['data']
    depart_simple_ids = para_data['depart_simple']['ids']
    # 删除用例的参数化数据和ids标题数据
    depart_explicit_data = para_data['depart_explicit']['data']
    depart_explicit_ids = para_data['depart_explicit']['ids']

    #
    # def setup_class(self,):
    #     print("abc")

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("增加联系人")
    @pytest.mark.parametrize(("userid,name,mobile,errcode,errmsg"),
                             add_data,
                             ids=add_ids)
    def test01_add_member(self, userid, name, mobile, errcode, errmsg, add):
        log.info(f"-------开始测试增加成员-------")
        res = self.member.add_member(self.token, userid, name, mobile)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("获得联系人信息")
    @pytest.mark.parametrize(("userid,errcode,errmsg"), get_data, ids=get_ids)
    def test02_get_member(self, userid, errcode, errmsg, get):
        log.info("-------开始测试获取成员-------")
        res = self.member.get_member_info(self.token, userid)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("删除联系人")
    @pytest.mark.parametrize(("userid,errcode,errmsg"),
                             delete_data,
                             ids=delete_ids)
    def test04_delete_member(self, userid, errcode, errmsg, delete):
        log.info("-------开始测试获取成员-------")
        res = self.member.delete_member(self.token, userid)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("批量删除联系人")
    @pytest.mark.parametrize(("userid_list,errcode,errmsg"),
                             multi_delete_data,
                             ids=multi_delete_ids)
    def test05_multi_delete_member(self, userid_list, errcode, errmsg,
                                   multi_delete):
        log.info("-------开始批量删除获取成员-------")
        res = self.member.multi_delete_member(self.token, userid_list)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("编辑联系人")
    @pytest.mark.parametrize(("userid,name,mobile,errcode,errmsg"),
                             edit_data,
                             ids=edit_ids)
    def test03_edit_member(self, userid, name, mobile, errcode, errmsg, edit):
        log.info("-------开始修改获取成员-------")
        res = self.member.edit_member(self.token, userid, name, mobile)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("查看企业微信活跃度")
    @pytest.mark.parametrize(("date,errcode,errmsg"),
                             active_data,
                             ids=active_ids)
    def test_active_stat(self, date, errcode, errmsg):
        log.info("-------开始查看企业微信活跃度-------")
        res = self.member.get_active_stat(self.token, date)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("增加联系人")
    @pytest.mark.parametrize(("size,errcode,errmsg"), qr_data, ids=qr_ids)
    def test_get_invite_qr(self, size, errcode, errmsg):
        log.info("-------开始获取企业微信二维码-------")
        res = self.member.get_invite_qr(self.token, size)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("查看部门联系人的简单信息")
    @pytest.mark.parametrize(("department_id,fetch_child,errcode,errmsg"),
                             depart_simple_data,
                             ids=depart_simple_ids)
    def test_get_depart_member(self, department_id, fetch_child, errcode,
                               errmsg):
        log.info("-------开始获取部门成员简单的信息-------")
        res = self.member.get_depart_member(self.token, department_id,
                                            fetch_child)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("查看部门联系人的复杂信息")
    @pytest.mark.parametrize(("department_id,fetch_child,errcode,errmsg"),
                             depart_explicit_data,
                             ids=depart_explicit_ids)
    def test_get_depart_member_explict(self, department_id, fetch_child,
                                       errcode, errmsg):
        log.info("-------开始部门成员详细信息-------")
        res = self.member.get_depart_member_explicit(self.token, department_id,
                                                     fetch_child)
        log.info(f"打印响应结果:{res}")
        log.info("-------测试结束-------")
        assert res["errcode"] == errcode
        assert errmsg in res["errmsg"]

    @allure.severity(allure.severity_level.BLOCKER)
    @allure.story("增加联系人")
    @pytest.mark.smoke
    def test_all_smoke_member(self, test_all_pre_data):
        add_res = self.member.add_member(self.token, "tong1234", "tong1234",
                                         "13172771165")
        edit_res = self.member.edit_member(self.token, "tong1234", "tong1234",
                                           "13172771165")
        del_res = self.member.delete_member(self.token, "tong1234")
        multi_del_res = self.member.multi_delete_member(
            self.token, ["tongtong1", "tongtong2", "tongtong3"])
        qr_res = self.member.get_invite_qr(self.token, 1)
        active_res = self.member.get_active_stat(self.token, "2020-10-10")
        depart_res = self.member.get_depart_member(self.token, "1", "1")
        depart_res_e = self.member.get_depart_member_explicit(
            self.token, "1", "1")
        assert add_res["errcode"] == 0
        assert edit_res["errcode"] == 0
        assert del_res["errcode"] == 0
        assert multi_del_res["errcode"] == 0
        assert qr_res["errcode"] == 0
        assert active_res["errcode"] == 0
        assert depart_res["errcode"] == 0
        assert depart_res_e["errcode"] == 0
        log.info("finish")

    def tear_down(self):
        pass
class Member(BaseApi):
    # 定义不同测试、生产环境的ip,通过配置文件获取
    env_ip = cf.get_key("env", "formal_ip")
    # 定义项目的绝对根路径
    BASE_PATH = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))

    # 封装从yml拿数据,并改变替换yml原本的$变量的数据
    def send_api_data(self, p_data, path):
        # 打印传入template要改变的$变量值
        log.info(f"template传入的p_data:{p_data}")
        # 读取yml文件的路径
        data_path = os.path.join(self.BASE_PATH, path)

        # 改变yml文件的$变量值
        data = self.template(data_path, p_data)
        log.info(f"请求的所有参数:{data}")
        res = self.send_api(data)
        return res

    def add_member(self, token, userid, name, mobile):
        p_data = {
            "token": token,
            "name": name,
            "userid": userid,
            "mobile": mobile
        }

        data_path = os.path.join(self.BASE_PATH, "data/member/add_member.yml")
        data = self.template(data_path, p_data)
        log.info(data)
        res = self.send_api(data)
        return res

    def get_member_info(self, token, userid):
        p_data = {"token": token, "userid": userid}
        data_path = os.path.join(self.BASE_PATH, "data/member/get_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    def edit_member(self, token, userid, name, mobile):
        p_data = {
            "token": token,
            "name": name,
            "userid": userid,
            "mobile": mobile
        }
        data_path = os.path.join(self.BASE_PATH, "data/member/edit_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    def delete_member(self, token, userid):
        p_data = {"token": token, "userid": userid}
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/delete_member.yml")
        data = self.template(data_path, p_data)
        log.info(f"请求的参数:{data}")
        res = self.send_api(data)
        return res

    def multi_delete_member(self, token, uesrid_list):
        p_data = {"token": token, "userid_list": uesrid_list}
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/multi_delete_member.yml")
        data = self.template(data_path, p_data)
        res = self.send_api(data)
        return res

    def get_depart_member(self, token, department_id, fetch_child):
        p_data = {
            "token": token,
            "department_id": department_id,
            "fetch_child": fetch_child
        }
        log.info(p_data)
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/get_depart_member.yml")
        data = self.template(data_path, p_data)
        log.info(data)
        res = self.send_api(data)
        return res

    def get_depart_member_explicit(self, token, department_id, fetch_child):
        p_data = {
            "token": token,
            "department_id": department_id,
            "fetch_child": fetch_child
        }
        log.info(p_data)
        data_path = os.path.join(self.BASE_PATH,
                                 "data/member/get_depart_member_explicit.yml")
        data = self.template(data_path, p_data)
        log.info(data)
        res = self.send_api(data)
        return res

    def get_invite_qr(self, token, size_type):
        p_data = {"token": token, "size_type": size_type}
        res = self.send_api_data(p_data, "data/member/get_invite_qr.yml")
        # p_data = {"token": token, "size_type": size_type}
        # data_path = os.path.join(self.BASE_PATH, "data/member/get_invite_qr.yml")
        # data = self.base.template(data_path, p_data)
        # res = self.send_api(data)
        return res

    def get_active_stat(self, token, date):
        p_data = {"ip": self.env_ip, "token": token, "date": date}
        res = self.send_api_data(p_data, "data/member/get_active_stat.yml")
        return res
Exemple #16
0
 def get_token(self):
     secret = cf.get_key("wwork", "contact_secret")
     access_token = Wework().get_token(secret)
     return access_token
Exemple #17
0
class MeetingRoom(BaseApi):
    """
    会议室的api类

    test_token: token值
    api_path: yml_api的相对路径
    """

    # 只是拿来测试用,可以不存在在这里
    test_token = Wework().get_token(cf.get_key("wwork", "meeting_room_secret"))
    # 简化send_api_data方法路径引用,不用写那么多路径了
    api_path = "data/meeting_room/meeting_room_api.yml"

    # 增加会议室
    def add_meeting_room(self, token, name, capacity, city, building, floor,
                         equipment):
        # Template模板二次修改的值,p_data
        p_data = {
            "ip": self.ip,
            "token": token,
            "name": name,
            "capacity": capacity,
            "city": city,
            "building": building,
            "floor": floor,
            "equipment": equipment
        }
        # 获取响应,进行了多次封装
        res = self.send_api_data(self.api_path, p_data, "add")
        return res

    # 编辑会议室
    def edit_meeting_room(self, token, meetingroom_id, name, capacity, city,
                          building, floor, equipment):
        p_data = {
            "ip": self.ip,
            "token": token,
            "meetingroom_id": meetingroom_id,
            "name": name,
            "capacity": capacity,
            "city": city,
            "building": building,
            "floor": floor,
            "equipment": equipment
        }
        res = self.send_api_data(self.api_path, p_data, "edit")
        return res

    # 删除会议室
    def delete_meeting_room(self, token, meetingroom_id):
        p_data = {
            "ip": self.ip,
            "token": token,
            "meetingroom_id": meetingroom_id
        }
        res = self.send_api_data(self.api_path, p_data, "delete")
        return res

    # 获取会议室
    def get_meeting_room(self, token, city, building, floor, equipment):
        p_data = {
            "ip": self.ip,
            "token": token,
            "city": city,
            "building": building,
            "floor": floor,
            "equipment": equipment
        }
        res = self.send_api_data(self.api_path, p_data, "get")
        return res