v2-79d673da2a7d949aab05aedeb2be9319_1440w.jpg?source=172ae18b

v2-9bdfbbf6c31e04536791bb004f34b7b9_b.jpg

上一次,我们新建了 core/rest_client.py 这个文件,并且可以使用其中的RestClient类来收发http请求。这一小节,我们接着上次的rest 请求客户端,向其中增加登录 Github的功能。

通过 API 登录 Github

在官方文档的这里:

https://developer.github.com/v3/#authentication

和这里:

https://developer.github.com/v3/auth/

介绍了 Github api 支持的登录方式:

1.用户名密码登录。最直接的方式,向服务端发送用户名密码来登录。此外,特定的一些 api 只能用这个方式登录。

2.token登录。最常用的方式,使用一个特殊字符串 token 来代替用户名密码,完成用户登录权限验证。

3.SAML登录。企业级里常用的方式,可以和企业里其他用户认证方式结合。

4.two-factor 登录。要求二次鉴权的登录方式,比如手机验证码登录。

在本教程中,我们将实现用户名密码登录和token登录两种方式。

例1.用户名密码登录和token登录的实现

class 

这里,通过修改 RestClient 类的初始化方法,添加了三个参数, username,password 和 token。

当 username 和 password 不为空时使用用户名密码登录,向 requests session 中添加 auth 信息。

当 token不为空时使用 token 登录,向 requests session 的 header 里的 Authorization 字段里添加 token 信息。

任务1. 修改 RestClient 类

上面例1的代码中,有一个bug, 当用户同时输入了username,password和token时,两种鉴权方式的信息都会被存入 session,这就有可能导致未知的错误,请尝试通过修改代码修复这个bug。

目录结构

接下来我们要封装一个 Github 接口,来看看登录的效果。在封装这个接口之前,我们来看看目录结构:

v2-df8a37e605fa54e90b15f6ba8fa5e2f9_b.jpg

如图所示,在 TUGithubAPI 工程目录下,我们新建了两个目录,分别是 api 和 core, core 里存放核心的工具类 RestClient, api 里则会存放封装好的接口类。而这两个目录外面还有一个 github.py,这个文件将作为总入口,提供给这个代码库的用户使用。

那么今天我们要用的 repos 接口是从 github 文档的这里查到的:

https://developer.github.com/v3/repos/

这里,我们注意到文档的导航栏里有:

v2-8a8147e481c2a8a1956bad544a1f22ba_b.jpg

这么多页面都挂在 Repositories 下面。没错,这些都是我们后续要实现的。现在我们的目录结构中,只有api/repositories/repos.py,那后面就会有其他这些,比如branches.py等。而其他接口则会放在其他目录下。比如 api/search目录会包含文档中 search下的接口。

v2-2aa2f4a63b4e463d1a6aeaade3e4781d_b.jpg

除了这些简单接口的封装,存放在 api 目录下以外,我们还会实现更业务化的连续操作,比如通过调用若干个接口实现一个完整功能,这种,我们将来会在 api目录同级别的地方建立 domain 目录,来存放这类用户操作。

在这个小节中,我们只是简单封装一下repos的一个接口,来看看登录前后调用接口的区别,下一小节才会正式封装这个接口。

封装第一个Github接口

我们开始写代码封装第一个接口。

例2. api/repositories/repos.py

from core.rest_client import RestClient
class Repos(RestClient):
    def __init__(self,api_root_url,**kwargs):
        super(Repos, self).__init__(api_root_url,**kwargs)


    def list_your_repos(self):
        return self.get("/user/repos")

例3.github.py

from api.repositories.repos import Repos


class Github():
    def __init__(self, **kwargs):
        self.api_root_url="http://api.github.com"
        self.repos = Repos(self.api_root_url,**kwargs)




if __name__ == '__main__':
    r=Github(token="xxxxxxxxxxxxxx")
    x= r.repos.list_your_repos()
    print(x.text)


    r=Github(username="xxxxxx",password="xxxxx")
    x= r.repos.list_your_repos()
    print(x.text)

介绍下例2和例3,

例2中,我们又建立了一个新的类Repos,Repos是 RestClient的一个子类。

值得注意的是,它的初始化方法有着和父类不一样的参数表(注意子类和父类的初始化方法可以接受不同的参数表):

def __init__(self, api_root_url,**kwargs)

它接受了一个固定参数 api_root_url, 和一个关键字参数 **kwargs。

其中 固定参数大家很好理解,而关键字参数的意思是,可以传入任意的键值对作为参数。当然了,观察其父类的代码我们就知道,这里虽然可以传任意的关键字参数,但只 username,password,token 这三个参数会被处理。这里的关键是:Repos 作为一个子类,它不需要知道哪些参数会被处理以及会被怎样处理,它就直接在自己的初始化方法里调用了父类的初始化方法,不论用户传入了几个参数,它都原封不动传给它的父类:

super(Repos, self).__init__(api_root_url,**kwargs)

这里的super就是表示父类,这一行调用的父类的 init 方法。

初始化完成后,自然就可以在子类中使用 self 来直接使用父类的方法了,比如 get 方法。

def list_your_repos(self):

return self.get("/user/repos")

现在我们不忙着运行例2 例3 的代码。先通过浏览器访问一下https://api.github.com/user/repos

得到响应如下:

401 Unauthorized
{ "message": "Requires authentication", "documentation_url": " https:// developer.github.com/v3 /repos/#list-your-repositories " }

这是因为,我们通过浏览器访问时,没有登录。系统返回401未授权的访问,并要求我们登录。

而运行例3的代码,则会得到你登录的用户的所有 repo信息。注意,把例3中的xxxxx信息改成你真实的信息。

例3 的代码中,我们使用了组合模式来做封装。组合模式,在 《java 编程思想》一书中有介绍。 这里就是借鉴了这个思路来写的。

首先我们建立一个 Github 类,Github 类负责接收用户输入的 用户名,密码,token, url 等参数,并且在其成员变量中去新建 repos 类的实例。而repos 类又继承自 RestClient 类。所以,相当于,一个 Github 类实例里有多个 RestClient的子类。类比于一辆车上有前轮后轮,而前轮后轮都是继承自轮子这个类。

本小节代码地址:

https://github.com/TestUpCommunity/TUGithubAPI/tree/teach_002


本文首发于测试进阶知识星球,

完整的接口测试教程正在我的知识星球火热更新中,

扫码即可加入。费用为128元/年。

关于项目实战的介绍:张挺:测试进阶社群项目实战启动

v2-9bdfbbf6c31e04536791bb004f34b7b9_b.jpg
Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐