예제 #1
0
class PingxxApi(BaseApi):
    __auth = None
    __rsa_private = None
    __config = read_yaml(current=__file__,
                         file_path="api.yml",
                         key="PingxxApi")

    def __init__(self, request, logger, secret_key: str, rsa_private: str):
        """
        构造 PingxxApi 的方法
        :param secret_key: 开发密钥
        :param rsa_private:  RSA商户私钥(需要整个字符串文本)
        """
        # 调用父类,完成父类的构造方法
        super().__init__(request=request, logger=logger)

        self.__auth = (secret_key, "")
        self.__rsa_private = rsa_private

    def _get_headers_for_signature(self, uri, request_body=None):
        """
        为签名验证构建请求头
        :param uri: URL 去掉 https://{host},从 / 开始
            注意:GET 请求需要传递全部的 uri,包含请求参数
        :param request_body: 请求的正文,如果没有就不传
        :return: dict
            返回的 字典直接用来做 请求头
            key 列表:
                - PingPlusPlus-Signature
                - PingPlusPlus-Request-Timestamp
        """
        if self.__rsa_private is None or self.__rsa_private == "":
            return {}
        signature, timestamp = self.request.get_sign_by_pkcs115(
            rsa_private_key=self.__rsa_private,
            uri=uri,
            body_params=request_body)
        self.info("[%r] - 获取 Ping++ 验签的请求头,使用数据 uri=%s, params=%r" %
                  (__name__, uri, request_body))

        headers = {
            self._get_config(data_dict=self.__config,
                             data_key="SIGN.HEADER_SIGNATURE"):
            signature,
            self._get_config(data_dict=self.__config,
                             data_key="SIGN.HEADER_TIMESTAMP"):
            timestamp
        }

        return headers

    @property
    def auth(self):
        """
        认证【属性】
        :return:
        """
        return self.__auth
예제 #2
0
    def test_charges_create(self, data):
        """
        执行测试的具体步骤
        :param data: 通过读取 __test_data_collection 得到一条 test_data
        :return: None
        """
        self.info("[%s] - 开始执行测试,使用数据:%r! " % (__name__, data))
        # 准备数据 从 test_data 取数据
        rsa_raw = data.get("RSA私钥")
        if rsa_raw is not None and rsa_raw != "":
            rsa_private = read_txt(current=__file__, file_path=rsa_raw)
        else:
            rsa_private = None

        extra_raw = data.get("extra")
        if extra_raw is not None and extra_raw != "":
            extra_value = read_yaml(current=__file__,
                                    file_path=extra_raw,
                                    key="%s/data/extra" % data.get("数据编号"))
        else:
            extra_value = None

        data_input_dict = dict(
            order_no=data.get("订单编号"),
            amount=data.get("金额"),
            channel=data.get("渠道"),
            currency=data.get("货币"),
            subject=data.get("主题"),
            body=data.get("正文"),
            description=data.get("描述"),
            extra=extra_value,
            app=dict(id=data.get("app")),
            client_ip=data.get("client_ip"),
            secret_key=data.get("密钥"),
            rsa_private=rsa_private,
            request=self.request,
            logger=self.logger
        )

        # 调用业务,使用上面准备的数据
        self.info("[%s] - 开始调用业务,使用数据 data_input_dict:%r! " % (__name__, data_input_dict))
        resp = biz_create_charge(data_input_dict)

        # 对比结果,使用 test_data 取到的期望,和上一步执行得到的结果进行对比
        self.info("[%s] - 开始进行断言,使用数据 resp:%r! " % (__name__, resp))
        assert self.assert_equal(expected=data.get("期望状态码"), actual=resp.get("status_code"))
        assert self.assert_equal(expected=data.get("期望object"), actual=resp.get("object"))
        assert self.assert_equal(expected=bool(data.get("期望paid")), actual=resp.get("paid"))
        assert self.assert_equal(expected=data.get("渠道"), actual=resp.get("channel"))
        assert self.assert_equal(expected=data.get("金额"), actual=resp.get("amount"))

        self.info("[%s] - 结束执行测试,使用数据:%r! " % (__name__, data))
예제 #3
0
class LoginPage(ZentaoPage):
    """
    author: ArtLinty
    email: [email protected]
    desc: 禅道企业版 登录页面业务
    """

    __config = read_yaml(current=__file__, file_path="web.yml", key="LoginPage")

    def login(self, account, password):
        """
        登录
        :param account:
        :param password:
        :return: 当前 URL
        """

        driver = self.driver

        driver.type(self._get_config(data_dict=self.__config, data_key="LOCATOR.ACCOUNT_INPUT"), account)
        driver.type(self._get_config(data_dict=self.__config, data_key="LOCATOR.PASSWORD_INPUT"), password)
        driver.click(self._get_config(data_dict=self.__config, data_key="LOCATOR.SUBMIT_BUTTON"))
        self.info("[%s] - 使用数据登录: %r" % (__name__, dict(account=account, password=password)))

        return self.current_url

    def set_language(self, language):
        """
        设定语言
        :param language:
            zh_hans: 中文简体
            zh_hant: 中文繁体
            en: 英文
            de: 德语
        :return:
        """
        if language is not None and isinstance(language, str):
            language = language.lower().strip()
        else:
            language = ""
        if language in ["zh_hans", "zh_hant", "en", "de"]:
            language_selector = "LOCATOR.%s_MENU" % language.upper()
            self.driver.click(self._get_config(data_dict=self.__config, data_key="LOCATOR.LANGUAGE_BUTTON"))
            self.driver.click(self._get_config(data_dict=self.__config, data_key=language_selector))
            self.info("[%s] - 设定语言为 %s" % (__name__, language_selector))

        return self.driver.get_text(self._get_config(
            data_dict=self.__config,
            data_key="LOCATOR.LANGUAGE_BUTTON"
        ))
예제 #4
0
class LifeApi(SeniverseApi):
    """
    标题: 生活类,生活模块的所有接口
    作者: 刘挺立
    日期: 20190820
    邮件: [email protected]
    """
    __config = read_yaml(current=__file__, file_path="api.yml", key="LifeApi")

    def suggest(self, data_dict):
        """
        生活指数
        :param data_dict:
        :return:
        """
        req_uri = self._get_config(self.__config, "SUGGEST.URI")
        req_method = self._get_config(self.__config, "SUGGEST.METHOD")
        req_data = {
            self._get_config(self.__config, "SUGGEST.PARAM.KEY"):
            self.api_key,
            self._get_config(self.__config, "SUGGEST.PARAM.LOCATION"):
            data_dict.get("location"),
            self._get_config(self.__config, "SUGGEST.PARAM.LANGUAGE"):
            data_dict.get("language")
        }
        req_data = self._remove_none_param(req_data)
        # 认证
        req_cookies = {}

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   data_dict=req_data,
                   cookies=req_cookies)
        # 返回响应的结果
        resp_body_key_list = self._get_config(self.__config,
                                              "SUGGEST.RESP.DATA_KEY")
        resp = self._parse(body_key_list=resp_body_key_list)

        # 处理 list
        list_data_key = self._get_config(self.__config,
                                         "SUGGEST.RESP.LIST.DATA_KEY")
        index = self._get_config(self.__config, "SUGGEST.RESP.LIST.INDEX")
        sub_data_key_list = self._get_config(self.__config,
                                             "SUGGEST.RESP.LIST.SUB_DATA_KEY")
        list_resp = self._parse_list(list_data_key=list_data_key,
                                     index=index,
                                     sub_data_key_list=sub_data_key_list)
        return self._merge_dict(resp, list_resp)
예제 #5
0
class IndexPage(LoginPage):
    """
    author: ArtLinty
    email: [email protected]
    desc: 禅道企业版 主页 业务
    """
    __config = read_yaml(current=__file__, file_path="web.yml", key="IndexPage")

    def get_real_name(self):
        """
        获取右上角真实姓名
        :return:
        """
        self.info("[%s] - 获取真实姓名! " % __name__)
        return self.driver.get_text(self._get_config(data_dict=self.__config, data_key="LOCATOR.REAL_NAME_SPAN"))

    def is_menu_active(self, menu: str):
        """
        判断菜单是否处于激活状态
        :param menu:
            my,
            product,
            project,
            qa,
            ops,
            oa,
            feedback,
            doc,
            report,
            company,
            admin
        :return:
        """
        if menu.strip() != "":
            menu = menu.lower().strip()
        if menu in ["my", "product", "project", "qa", "ops", "oa", "feedback", "doc", "report", "company", "admin"]:
            selector = self._get_config(data_dict=self.__config, data_key="LOCATOR.%s_LI" % menu.upper())

        else:
            selector = None

        if selector is not None:
            self.info("[%s] - 获取菜单的选中状态,数据是 %r! " % (__name__, dict(menu=menu)))
            return "active" in self.driver.get_attribute(
                selector,
                "class"
            )

        return None
예제 #6
0
class WeatherApi(SeniverseApi):
    """
    标题: 天气类,天气模块的所有接口
    作者: 梁静
    日期: 190826
    邮件: [email protected]
    """
    __config = read_yaml(current=__file__,
                         file_path="api.yml",
                         key="WeatherApi")

    def now(self, data_dict):
        """
        当前天气
        :param self:
        :param data_dict:
        :return:
        """
        req_uri = self._get_config(self.__config, "NOW.URI")
        self.info("[%s] - 使用 URI %r " % (__name__, req_uri))

        req_method = self._get_config(self.__config, "NOW.METHOD")
        self.info("[%s] - 使用 METHOD %r " % (__name__, req_method))
        req_data = {
            self._get_config(self.__config, "NOW.PARAM.KEY"):
            self.api_key,
            self._get_config(self.__config, "NOW.PARAM.LOCATION"):
            data_dict.get("location"),
            self._get_config(self.__config, "NOW.PARAM.LANGUAGE"):
            data_dict.get("language"),
            self._get_config(self.__config, "NOW.PARAM.UNIT"):
            data_dict.get("unit")
        }
        self.info("[%s] - 开始使用 参数 %r " % (__name__, req_data))

        req_data = self._remove_none_param(req_data)
        self.info("[%s] - 完成去空 参数 %r " % (__name__, req_data))

        # 认证
        req_cookies = {}

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   data_dict=req_data,
                   cookies=req_cookies)
        self.info("[%s] - 发送请求,使用数据如下 %r " % (__name__,
                                              dict(uri=req_uri,
                                                   method=req_method,
                                                   data_dict=req_data,
                                                   cookies=req_cookies)))

        # 返回响应的结果
        resp_body_key_list = self._get_config(self.__config,
                                              "NOW.RESP.LIST.DATA_KEY")
        self.info("[%s] - 读取响应数据键 %r " % (__name__, resp_body_key_list))

        resp = self._parse(body_key_list=resp_body_key_list)
        self.info("[%s] - 收到 响应 %r " % (__name__, resp))

        # 处理list
        list_data_key = self._get_config(self.__config,
                                         "NOW.RESP.LIST.DATA_KEY")
        index = self._get_config(self.__config, "NOW.RESP.LIST.INDEX")
        sub_data_key_list = self._get_config(self.__config,
                                             "NOW.RESP.LIST.SUB_DATA_KEY")
        list_resp = self._parse_list(list_data_key=list_data_key,
                                     index=index,
                                     sub_data_key_list=sub_data_key_list)
        self.info("[%s] - 收到自定义解析响应 %r" % (__name__, list_resp))

        resp_result = self._merge_dict(resp, list_resp)
        self.info("[%s] - 合并之前的解析 %r 和刚刚的自定义解析 %r " %
                  (__name__, resp, list_resp))

        return resp_result
예제 #7
0
class TestLogin(BaseTest):
    """
    author: ArtLinty
    email: [email protected]
    desc: 测试测试禅道登录业务
    """
    __test = dict(
        collection=read_csv(current=__file__, file_path="test_login.csv"),
        url=read_yaml(current=__file__, file_path="../../config/env_active.yml", key="zentao.url"),
        title="在登录页面,使用合法数据登录,操作成功",
        case="https://dwz.cn/GUIf2ZeN",
        feature="登录",
        story="系统登录操作",
        tag=("web", "zentao", "login", "valid"),
        severity=allure.severity_level.CRITICAL
    )

    @pytest.fixture(autouse=True)
    def prepare(self):
        """
        测试固件
        :return:
        """

        self.init_logger(__name__)
        self.init_driver(url=self.__test.get("url"))

        yield
        self.close_driver()

    @allure.feature(__test.get("feature"))
    @allure.story(__test.get("story"))
    @allure.tag(*__test.get("tag"))
    @allure.severity(__test.get("severity"))
    @allure.testcase(url=__test.get("case"))
    @allure.title(__test.get("title"))
    @pytest.mark.parametrize("data", __test.get("collection"))
    def test_login(self, data):
        """
        测试登录,合法数据正常登录
        :param data:
        :return:
        """

        account = data.get("account")
        password = data.get("password")
        language = data.get("language")

        actual_lang_button_text = biz_set_language(
            driver=self.driver,
            language=language,
            logger=self.logger
        )
        self.snapshot("在登录页面设置语言后截图=%r" % data)
        self.info("[%s] - 在登录页面设置语言,使用数据: %r" % (__name__, dict(language=language)))
        assert self.assert_equal(expected=data.get("exp_button_lang"), actual=actual_lang_button_text)

        current_url, actual_real_name = biz_get_real_name_after_login(
            driver=self.driver,
            account=account,
            password=password,
            logger=self.logger
        )

        self.info(
            "[%r]-登录禅道, 使用数据 account=%r, password=%r"
            % (__file__, account, password)
        )
        self.snapshot("登录后截图数据=%r" % data)
        expected = data.get("expected_url")
        assert self.assert_in(
            expected=expected,
            actual=current_url
        ), "登录后URL地址不对, expected=%r, actual=%r, 当前数据=%r" % (expected, current_url, data)

        expected = data.get("expected_real_name")
        assert self.assert_in(
            expected=expected,
            actual=actual_real_name
        ), "登录后 realname 地址不对, expected=%r, actual=%r, 当前数据=%r" % (expected, actual_real_name, data)
예제 #8
0
class ChargeApi(PingxxApi):
    """
    标题: 业务类,普通支付模块的所有接口
    作者: 刘挺立
    日期: 20190819
    邮件: [email protected]
    """
    __config = read_yaml(current=__file__,
                         file_path="api.yml",
                         key="ChargeApi")

    def create(self, data_dict: dict):
        """
        真实的调用 POST /v1/charges 接口
        :param data_dict:  dict
            需要的key
                order_no
                amount,
                channel,
                currency,
                subject,
                body,
                description,
                extra: 需要是个字典,根据 channel
                app: 需要是个字典,{"id": your_app_id}
        :return:
        """
        # 格式化处理请求的数据
        # URI
        req_uri = self._get_config(self.__config, "CREATE.URI")
        req_method = self._get_config(self.__config, "CREATE.METHOD")
        req_data = {
            self._get_config(self.__config, "CREATE.PARAM.APP"):
            data_dict.get("app"),
            self._get_config(self.__config, "CREATE.PARAM.ORDER_NO"):
            data_dict.get("order_no"),
            self._get_config(self.__config, "CREATE.PARAM.CHANNEL"):
            data_dict.get("channel"),
            self._get_config(self.__config, "CREATE.PARAM.AMOUNT"):
            data_dict.get("amount"),
            self._get_config(self.__config, "CREATE.PARAM.CLIENT_IP"):
            data_dict.get("client_ip"),
            self._get_config(self.__config, "CREATE.PARAM.CURRENCY"):
            data_dict.get("currency"),
            self._get_config(self.__config, "CREATE.PARAM.SUBJECT"):
            data_dict.get("subject"),
            self._get_config(self.__config, "CREATE.PARAM.BODY"):
            data_dict.get("body"),
            self._get_config(self.__config, "CREATE.PARAM.DESCRIPTION"):
            data_dict.get("description"),
            self._get_config(self.__config, "CREATE.PARAM.EXTRA"):
            data_dict.get("extra")
        }
        req_data = self._remove_none_param(req_data)
        # 认证
        req_auth = self.auth
        req_cookies = {}
        req_headers = self._get_headers_for_signature(uri=req_uri,
                                                      request_body=req_data)
        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   data_dict=req_data,
                   auth=req_auth,
                   cookies=req_cookies,
                   headers=req_headers)
        # 返回响应的结果
        resp_body_key_list = self._get_config(self.__config,
                                              "CREATE.RESP.DATA_KEY")
        return self._parse(body_key_list=resp_body_key_list)

    def view(self, charge_id: str):
        """
        真实的调用 GET /v1/charges/{charge_id} 接口
        :param charge_id:
        :return:
        """
        # 格式化处理请求的数据
        req_uri = self._get_config(self.__config, "VIEW.URI") % charge_id
        req_method = self._get_config(self.__config, "VIEW.METHOD")
        req_auth = self.auth
        req_cookies = {}
        req_headers = self._get_headers_for_signature(uri=req_uri)

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   auth=req_auth,
                   cookies=req_cookies,
                   headers=req_headers)
        resp_body_key_list = self._get_config(self.__config,
                                              "VIEW.RESP.DATA_KEY")
        return self._parse(body_key_list=resp_body_key_list)

    def query(self, data_dict: dict):
        """
        真实的调用 GET /v1/charges/xxxx=xxxx 接口
        :param data_dict:
        :return:
        """
        # 格式化处理请求的数据
        req_uri = self._get_config(self.__config, "VIEW.URI")
        req_method = self._get_config(self.__config, "VIEW.METHOD")
        req_data = {
            self._get_config(self.__config, "CREATE.PARAM.APP.get(id)"):
            data_dict.get("app"),
            self._get_config(self.__config, "CREATE.PARAM.LIMIT"):
            data_dict.get("limit"),
            self._get_config(self.__config, "CREATE.PARAM.CHANNEL"):
            data_dict.get("channel"),
            self._get_config(self.__config, "CREATE.PARAM.REFUNDED"):
            data_dict.get("refunded"),
            self._get_config(self.__config, "CREATE.PARAM.REVERSED"):
            data_dict.get("reversed"),
            self._get_config(self.__config, "CREATE.PARAM.PAID"):
            data_dict.get("paid"),
            self._get_config(self.__config, "CREATE.PARAM.CREATED_GT"):
            data_dict.get("created_gt"),
            self._get_config(self.__config, "CREATE.PARAM.CREATED_LT"):
            data_dict.get("created_lt"),
            self._get_config(self.__config, "CREATE.PARAM.CREATED_GTE"):
            data_dict.get("created_gte"),
            self._get_config(self.__config, "CREATE.PARAM.CREATED_LTE"):
            data_dict.get("created_lte")
        }
        req_data = self._remove_none_param(req_data)
        req_uri = encode_url(url=req_uri, params=req_data)
        req_auth = self.auth

        req_cookies = {}
        req_headers = self._get_headers_for_signature(uri=req_uri)

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   auth=req_auth,
                   cookies=req_cookies,
                   headers=req_headers)
        resp_body_key_list = self._get_config(self.__config,
                                              "VIEW.RESP.DATA_KEY")
        return self._parse(body_key_list=resp_body_key_list)

    def reverse(self, charge_id):
        """
        真实的调用 POST .v1.charges.{charge_id}.reverse 接口
        :param charge_id:
        :return:
        """
        # 格式化处理请求的数据
        # URI
        # 格式化处理请求的数据
        req_uri = self._get_config(self.__config, "REVERSE.URI") % charge_id
        req_method = self._get_config(self.__config, "REVERSE.METHOD")
        req_auth = self.auth
        req_cookies = {}
        req_headers = self._get_headers_for_signature(uri=req_uri)

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   auth=req_auth,
                   cookies=req_cookies,
                   headers=req_headers)
        resp_body_key_list = self._get_config(self.__config,
                                              "REVERSE.RESP.DATA_KEY")
        return self._parse(body_key_list=resp_body_key_list)
예제 #9
0
class TestWeatherNow(BaseTest):
    """
    标题: 在天气指数接口,使用合法有效的数据请求  查询天气指数接口,查询成功
    作者: 梁静
    时间: 20190826
    邮件: [email protected]
    """
    __test = dict(
        collection=read_csv(current=__file__, file_path="test_weather_now.csv"),
        config=read_yaml(current=__file__, file_path="../../config/env_active.yml", key="seniverse"),
        title="在天气指数接口,使用合法有效的数据请求  查询天气指数接口,查询成功",
        case="",
        feature="天气接口",
        story="天气接口的查询",
        tag=("api", "seniverse", "view", "valid"),
        severity=allure.severity_level.NORMAL
    )

    @pytest.fixture(autouse=True)
    def prepare(self):
        """
        测试执行使用的测试固件,包含前置条件和清理操作
        :return:
        """
        # 首先是前置条件,在yeild之前
        # 准备日志条件,就可以记录整个测试
        self.init_logger(__name__)
        # 准备请求对象,就可以传递请求给业务,也可以对请求进行抓包截图
        self.init_request(
            schema=parse_dict(dict_data=self.__test, data_key="config.schema"),
            host=parse_dict(dict_data=self.__test, data_key="config.host")
        )
        # 是 yeild 的关键字,代表执行test_ 开头的方法的具体内容
        self.info("[%s]- 完成测试的前置条件 set_up!  " % __name__)
        yield
        # 接下来是 清理操作
        self.close_request()
        self.wait()
        self.info("[%s]- 完成测试的清理操作  tear_up!" % __name__)

    @allure.feature(__test.get("feature"))
    @allure.story(__test.get("story"))
    @allure.tag(*__test.get("tag"))
    @allure.severity(__test.get("severity"))
    @allure.testcase(url=__test.get("case"))
    @allure.title(__test.get("title"))
    @pytest.mark.parametrize("data", __test.get("collection"))
    def test_weather_now(self, data):
        """
        执行测试的具体步骤

        :param data: 通过读取__test_data_collection 得到一套 test_data
        :return: none
        """
        self.info("[%s]-开始执行测试 ,使用数据:%r !" % (__name__, data))
        # 准备数据  从test_data 取数据
        data_input_dict = dict(
            api_key=data.get("私钥"),
            location=data.get("location"),
            language=data.get("language"),
            unit=data.get("unit"),
            request=self.request,
            logger=self.logger
        )

        # 调用业务,使用上面的数据
        self.info("[%s]-调用业务,使用数据data_input_dict:%r !" % (__name__, data_input_dict))
        resp = biz_view_weather_now(data_input_dict)
        # 对比结果,使用test_data取得的期望,和上一步取得的结果进行对比
        self.info("[%s]-开始进行断言,使用rasp:%r !" % (__name__, resp))
        assert self.assert_equal(expected=data.get("期望状态码"), actual=resp.get("status_code"))
        assert self.assert_equal(expected=data.get("期望城市名称"), actual=resp.get("location.name"))
        assert self.assert_equal(expected=data.get("期望国家代号"), actual=resp.get("location.country"))
        assert self.assert_equal(expected=data.get("期望城市代码"), actual=resp.get("location.id"))

        self.info("[%s]-结束执行测试,使用数据:%r !" % (__name__, data))
예제 #10
0
class VvtechApi(BaseApi):
    __token = None
    __config = read_yaml(current=__file__,
                         file_path="api.yml",
                         key="VvtechApi")

    def login(self, data_dict: dict):
        """
        登录
        :param data_dict:
        :return:
        """
        req_uri = self._get_config(self.__config, "LOGIN.URI")
        req_method = self._get_config(self.__config, "LOGIN.METHOD")
        req_data = {
            self._get_config(self.__config, "SIGN.BODY_VV_SIGNATURE"):
            data_dict.get("vv_signature"),
            self._get_config(self.__config, "SIGN.BODY_VV_TIME"):
            data_dict.get("vv_time"),
            self._get_config(self.__config, "LOGIN.PARAM.PASSWORD"):
            data_dict.get("password"),
            self._get_config(self.__config, "LOGIN.PARAM.IS_ANDROID"):
            data_dict.get("is_android"),
            self._get_config(self.__config, "LOGIN.PARAM.CLIENT_ID"):
            data_dict.get("client_id"),
            self._get_config(self.__config, "LOGIN.PARAM.MOBILE"):
            data_dict.get("mobile"),
            self._get_config(self.__config, "LOGIN.PARAM.VERSION"):
            data_dict.get("version")
        }
        req_data = self._remove_none_param(req_data)
        # 认证
        # 真正的发请求
        self._send(uri=req_uri, method=req_method, data_dict=req_data)
        # 返回响应的结果
        resp_body_key_list = self._get_config(data_dict=self.__config,
                                              data_key="LOGIN.RESP.DATA_KEY")
        resp = self._parse(body_key_list=resp_body_key_list)

        data_key_token = self._get_config(self.__config,
                                          "LOGIN.RESP.DATA_KEY_TOKEN")
        self.__token = parse_dict(dict_data=resp, data_key=data_key_token)
        return resp

    def _get_body_for_signature(self, token, request_body=None):
        """
        为签名验证构建请求头
        :param uri: URL 去掉 https://{host},从 / 开始
            注意:GET 请求需要传递全部的 uri,包含请求参数
        :param request_body: 请求的正文,如果没有就不传
        :return: dict
            返回的 字典直接用来做 请求头
            key 列表:
                - PingPlusPlus-Signature
                - PingPlusPlus-Request-Timestamp
        """
        if self.token is None or self.token == "":
            token = self.token
        signature, timestamp = self.request.get_sign_by_md5(
            token=token, body_params=request_body)
        self.info("[%r] - 获取 VVTECH 验签的请求正文,使用数据 token=%s, params=%r" %
                  (__name__, token, request_body))

        body = {
            self._get_config(data_dict=self.__config,
                             data_key="SIGN.BODY_VV_SIGNATURE"):
            signature,
            self._get_config(data_dict=self.__config,
                             data_key="SIGN.BODY_VV_TIME"):
            timestamp
        }

        return body

    @property
    def token(self):
        """
        认证【属性】
        :return:
        """
        return self.__token
예제 #11
0
class WithdrawApi(VvtechApi):
    """
    标题: 业务类,普通支付模块的所有接口
    作者: 刘挺立
    日期: 20190819
    邮件: [email protected]
    """
    __config = read_yaml(current=__file__,
                         file_path="api.yml",
                         key="WithdrawApi")

    def add(self, data_dict: dict):
        """
        真实的调用 POST /v1/charges 接口
        :param data_dict:  dict
            需要的key
                order_no
                amount,
                channel,
                currency,
                subject,
                body,
                description,
                extra: 需要是个字典,根据 channel
                app: 需要是个字典,{"id": your_app_id}
        :return:
        """
        # 格式化处理请求的数据
        # URI
        req_uri = self._get_config(self.__config, "ADD.URI")
        req_method = self._get_config(self.__config, "ADD.METHOD")
        token = data_dict.get("token")
        if token is None or token == "":
            token = self.token

        req_data = {
            self._get_config(self.__config, "ADD.PARAM.PASSWORD"):
            data_dict.get("password"),
            self._get_config(self.__config, "ADD.PARAM.BANK_CARD_ID"):
            data_dict.get("bank_card_id"),
            self._get_config(self.__config, "ADD.PARAM.AMOUNT"):
            data_dict.get("amount"),
            self._get_config(self.__config, "ADD.PARAM.APP_SECRET"):
            data_dict.get("app_secret")
        }
        req_data = self._remove_none_param(req_data)
        # 认证
        req_body = self._get_body_for_signature(token=token,
                                                request_body=req_data)

        req_data_after_sign = self._merge_dict(first_dict=req_data,
                                               second_dict=req_body)
        req_data_after_sign[self._get_config(self.__config,
                                             "ADD.PARAM.TOKEN")] = token

        # 真正的发请求
        self._send(uri=req_uri,
                   method=req_method,
                   data_dict=req_data_after_sign)
        # 返回响应的结果
        resp_body_key_list = self._get_config(self.__config,
                                              "ADD.RESP.DATA_KEY")
        return self._parse(body_key_list=resp_body_key_list)
예제 #12
0
class TestChargesCreate(BaseTest):
    """
    标题: 在支付对象接口,使用合法有效的数据请求 创建支付的接口,创建成功
    作者: 刘挺立
    时间: 20190813
    邮件: [email protected]
    """
    __test = dict(
        collection=read_csv(current=__file__, file_path="test_charges_create.csv"),
        config=read_yaml(current=__file__, file_path="../../config/env_active.yml", key="pingxx"),
        title="在支付对象接口,使用合法有效的数据请求,创建支付的接口,创建成功",
        case="https://dwz.cn/GUIf2ZeN",
        feature="支付接口",
        story="支付对象的创建",
        tag=("api", "pingxx", "create", "valid"),
        severity=allure.severity_level.CRITICAL
    )

    @pytest.fixture(autouse=True)
    def prepare(self):
        """
        测试执行使用的测试固件,包含前置条件和清理操作
        :return: None
        """
        # 首先是前置条件,在 yield 之前
        # 准备日志文件,就可以记录整个测试
        self.init_logger(__name__)
        # 准备请求对象,就可以传递请求给业务,也可以对请求进行抓包截图
        self.init_request(
            schema=parse_dict(dict_data=self.__test, data_key="config.schema"),
            host=parse_dict(dict_data=self.__test, data_key="config.host")
        )
        # 是 yield 关键字,代表执行 test_ 开头的方法的具体内容
        self.info("[%s] - 完成测试的前置条件 set_up! " % __name__)
        yield

        # 最后是清理操作,在 yield 之后
        self.wait()
        self.info("[%s] - 完成测试的清理操作 tear_down! " % __name__)

    @allure.feature(__test.get("feature"))
    @allure.story(__test.get("story"))
    @allure.tag(*__test.get("tag"))
    @allure.severity(__test.get("severity"))
    @allure.testcase(url=__test.get("case"))
    @allure.title(__test.get("title"))
    @pytest.mark.parametrize("data", __test.get("collection"))
    def test_charges_create(self, data):
        """
        执行测试的具体步骤
        :param data: 通过读取 __test_data_collection 得到一条 test_data
        :return: None
        """
        self.info("[%s] - 开始执行测试,使用数据:%r! " % (__name__, data))
        # 准备数据 从 test_data 取数据
        rsa_raw = data.get("RSA私钥")
        if rsa_raw is not None and rsa_raw != "":
            rsa_private = read_txt(current=__file__, file_path=rsa_raw)
        else:
            rsa_private = None

        extra_raw = data.get("extra")
        if extra_raw is not None and extra_raw != "":
            extra_value = read_yaml(current=__file__,
                                    file_path=extra_raw,
                                    key="%s/data/extra" % data.get("数据编号"))
        else:
            extra_value = None

        data_input_dict = dict(
            order_no=data.get("订单编号"),
            amount=data.get("金额"),
            channel=data.get("渠道"),
            currency=data.get("货币"),
            subject=data.get("主题"),
            body=data.get("正文"),
            description=data.get("描述"),
            extra=extra_value,
            app=dict(id=data.get("app")),
            client_ip=data.get("client_ip"),
            secret_key=data.get("密钥"),
            rsa_private=rsa_private,
            request=self.request,
            logger=self.logger
        )

        # 调用业务,使用上面准备的数据
        self.info("[%s] - 开始调用业务,使用数据 data_input_dict:%r! " % (__name__, data_input_dict))
        resp = biz_create_charge(data_input_dict)

        # 对比结果,使用 test_data 取到的期望,和上一步执行得到的结果进行对比
        self.info("[%s] - 开始进行断言,使用数据 resp:%r! " % (__name__, resp))
        assert self.assert_equal(expected=data.get("期望状态码"), actual=resp.get("status_code"))
        assert self.assert_equal(expected=data.get("期望object"), actual=resp.get("object"))
        assert self.assert_equal(expected=bool(data.get("期望paid")), actual=resp.get("paid"))
        assert self.assert_equal(expected=data.get("渠道"), actual=resp.get("channel"))
        assert self.assert_equal(expected=data.get("金额"), actual=resp.get("amount"))

        self.info("[%s] - 结束执行测试,使用数据:%r! " % (__name__, data))
예제 #13
0
class TestWithdrawAdd(BaseTest):
    """
    标题: 在支付对象接口,使用合法有效的数据请求 创建支付的接口,创建成功
    作者: 刘挺立
    时间: 20190813
    邮件: [email protected]
    """
    __test = dict(collection=read_csv(current=__file__,
                                      file_path="test_withdraw_add.csv"),
                  config=read_yaml(current=__file__,
                                   file_path="../../config/env_active.yml",
                                   key="vvtech"),
                  title="在支付对象接口,使用合法有效的数据请求,创建支付的接口,创建成功",
                  case="https://dwz.cn/GUIf2ZeN",
                  feature="取款接口",
                  story="取款对象的创建",
                  tag=("api", "vvtech", "add", "valid"),
                  severity=allure.severity_level.CRITICAL)

    @pytest.fixture(autouse=True)
    def prepare(self):
        """
        测试执行使用的测试固件,包含前置条件和清理操作
        :return: None
        """
        # 首先是前置条件,在 yield 之前
        # 准备日志文件,就可以记录整个测试
        self.init_logger(__name__)
        # 准备请求对象,就可以传递请求给业务,也可以对请求进行抓包截图
        self.init_request(schema=parse_dict(dict_data=self.__test,
                                            data_key="config.schema"),
                          host=parse_dict(dict_data=self.__test,
                                          data_key="config.host"))
        # 是 yield 关键字,代表执行 test_ 开头的方法的具体内容
        self.info("[%s] - 完成测试的前置条件 set_up! " % __name__)
        yield

        # 最后是清理操作,在 yield 之后
        self.wait()
        self.info("[%s] - 完成测试的清理操作 tear_down! " % __name__)

    @allure.feature(__test.get("feature"))
    @allure.story(__test.get("story"))
    @allure.tag(*__test.get("tag"))
    @allure.severity(__test.get("severity"))
    @allure.testcase(url=__test.get("case"))
    @allure.title(__test.get("title"))
    @pytest.mark.parametrize("data", __test.get("collection"))
    def test_charges_create(self, data):
        """
        执行测试的具体步骤
        :param data: 通过读取 __test_data_collection 得到一条 test_data
        :return: None
        """
        self.info("[%s] - 开始执行测试,使用数据:%r! " % (__name__, data))
        # 准备数据 从 test_data 取数据

        data_input_dict = dict(vv_vv_signature=data.get("签名"),
                               vv_time=data.get("时间戳"),
                               app_secret=data.get("密钥"),
                               client_id=data.get("客户编号"),
                               password=data.get("密码"),
                               is_android=data.get("平台"),
                               mobile=data.get("手机号"),
                               version=data.get("版本"),
                               amount=data.get("金额"),
                               bank_card_id=data.get("卡号"),
                               request=self.request,
                               logger=self.logger)

        # 调用业务,使用上面准备的数据
        self.info("[%s] - 开始调用业务,使用数据 data_input_dict:%r! " %
                  (__name__, data_input_dict))
        resp, resp2 = biz_add_withdraw(data_input_dict)

        # 对比结果,使用 test_data 取到的期望,和上一步执行得到的结果进行对比
        self.info("[%s] - 开始进行断言,使用数据 resp:%r! " % (__name__, resp))
        assert self.assert_equal(expected=data.get("期望状态码"),
                                 actual=resp.get("status_code"))
        assert self.assert_equal(expected=data.get("期望状态码"),
                                 actual=resp2.get("status_code"))
        assert self.assert_int_equal(expected=data.get("期望flag"),
                                     actual=resp2.get("flag"))

        self.info("[%s] - 结束执行测试,使用数据:%r! " % (__name__, data))
예제 #14
0
class TestLifeSuggest(BaseTest):
    """
    标题: 在生活指数接口,使用合法有效的数据请求 查询生活指数的接口,查询成功
    作者: 刘挺立
    时间: 20190814
    邮件: [email protected]
    """
    __test = dict(collection=read_csv(current=__file__,
                                      file_path="test_life_suggest.csv"),
                  config=read_yaml(current=__file__,
                                   file_path="../../config/env_active.yml",
                                   key="seniverse"),
                  title="在生活指数接口,使用合法有效的数据请求 查询生活指数的接口,查询成功",
                  case="https://dwz.cn/GUIf2ZeN",
                  feature="生活接口",
                  story="生活指数的查询",
                  tag=("api", "seniverse", "view", "valid"),
                  severity=allure.severity_level.CRITICAL)

    @pytest.fixture(autouse=True)
    def prepare(self):
        """
        测试执行使用的测试固件,包含前置条件和清理操作
        :return: None
        """
        # 首先是前置条件,在 yield 之前
        # 准备日志文件,就可以记录整个测试
        self.init_logger(__name__)
        # 准备请求对象,就可以传递请求给业务,也可以对请求进行抓包截图
        self.init_request(schema=parse_dict(dict_data=self.__test,
                                            data_key="config.schema"),
                          host=parse_dict(dict_data=self.__test,
                                          data_key="config.host"))
        # 是 yield 关键字,代表执行 test_ 开头的方法的具体内容
        self.info("[%s] - 完成测试的前置条件 set_up! " % __name__)
        yield

        # 最后是清理操作,在 yield 之后
        self.wait()
        self.info("[%s] - 完成测试的清理操作 tear_down! " % __name__)

    @allure.feature(__test.get("feature"))
    @allure.story(__test.get("story"))
    @allure.tag(*__test.get("tag"))
    @allure.severity(__test.get("severity"))
    @allure.testcase(url=__test.get("case"))
    @allure.title(__test.get("title"))
    @pytest.mark.parametrize("data", __test.get("collection"))
    def test_life_suggest(self, data):
        """
        执行测试的具体步骤
        :param data: 通过读取 __test_data_collection 得到一条 test_data
        :return: None
        """
        self.info("[%s] - 开始执行测试,使用数据:%r! " % (__name__, data))
        # 准备数据 从 test_data 取数据
        data_input_dict = dict(api_key=data.get("私钥"),
                               location=data.get("location"),
                               language=data.get("language"),
                               request=self.request,
                               logger=self.logger)

        # 调用业务,使用上面准备的数据
        self.info("[%s] - 开始调用业务,使用数据 data_input_dict:%r! " %
                  (__name__, data_input_dict))
        resp = biz_view_life_suggestion(data_input_dict)

        # 对比结果,使用 test_data 取到的期望,和上一步执行得到的结果进行对比
        self.info("[%s] - 开始进行断言,使用数据 resp:%r! " % (__name__, resp))
        assert self.assert_equal(expected=data.get("期望状态码"),
                                 actual=resp.get("status_code"))
        assert self.assert_equal(expected=data.get("期望城市名称"),
                                 actual=resp.get("location.name"))
        assert self.assert_equal(expected=data.get("期望国家代号"),
                                 actual=resp.get("location.country"))

        self.info("[%s] - 结束执行测试,使用数据:%r! " % (__name__, data))