赵兰 發表於 2020-4-20 14:35:00

Python接口测试课程(第一天)-Python基础

<h2 id="目录">目录</h2>
<p>Python接口测试课程(第一天)-Python基础<br>
Python接口测试课程(第二天)-接口测试快速实践<br>
Python接口测试课程(第三天)-接口安全验证,参数化及断言<br>
Python接口测试课程(第四天)-接口测试框架实现</p>
<blockquote>
<p>PDF下载:链接:https://pan.baidu.com/s/1x3_LYq23F_1LviGVbRNFXw密码:xrcj</p>
</blockquote>
<blockquote>
<p>更多学习资料请加添加作者微信:superz-han 获取</p>
</blockquote>
<h2 id="第一天-python基础">第一天: Python基础</h2>
<p><img src="https://upload-images.jianshu.io/upload_images/7575721-c7ee679b2a678a9a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="大纲" loading="lazy"></p>
<h3 id="python简介环境搭建及包管理">Python简介、环境搭建及包管理</h3>
<h4 id="python简介">Python简介</h4>
<ol>
<li>特点:Python是一门动态、解释型、强类型语言
<ol>
<li>动态:在运行期间才做数据检查(不用提前声明变量)- 静态语音(C/Java):编译时检查数据类型(编码时需要声明变量类型)</li>
<li>解释型:在执行程序时,才一条条解释成机器语言给计算机执行(无需编译,速度较慢)- 编译型语言(C/Java):先要将代码编译成二进制可执行文件,再执行</li>
<li>强类型:类型安全,变量一旦被指定了数据类型,如果不强制转换,那么永远是这种类型(严谨,避免类型错误,速度较慢)- 弱类型(VBScript/JavaScript): 类型在运行期间会转化,如 js中的 1+"2"="12", 1会由数字转化为string</li>
</ol>
</li>
<li>编码原则:优雅、明确、简单</li>
<li>优点
<ol>
<li>简单易学</li>
<li>开发效率高</li>
<li>高级语言</li>
<li>可移植、可扩展、可嵌入</li>
<li>庞大的三方库</li>
</ol>
</li>
<li>缺点
<ol>
<li>速度慢</li>
<li>代码不能加密</li>
<li>多线程不能充分利用多核cpu(GIL全局解释性锁,同一时刻只能运行一个线程)</li>
</ol>
</li>
<li>应用领域
<ol>
<li>自动化测试(UI/接口)</li>
<li>自动化运维</li>
<li>爬虫</li>
<li>Web开发(Django/Flask/..)</li>
<li>图形GUI开发</li>
<li>游戏脚本</li>
<li>金融、量化交易</li>
<li>数据分析,大数据</li>
<li>人工智能、机器学习、NLP、计算机视觉</li>
<li>云计算</li>
</ol>
</li>
</ol>
<h4 id="环境搭建">环境搭建</h4>
<p>Windows Python3环境搭建</p>
<ol>
<li>下载Python3.6.5*.exe安装包</li>
<li>双击安装,第一个节目选中Add Python3.6.5 to PATH,点击Install Now(默认安装pip),一路下一步</li>
<li>验证:打开cmd命令行,输入python,应能进入python shell 并显示为Python 3.6.5版本</li>
</ol>
<h4 id="包管理">包管理</h4>
<ol>
<li>pip安装
<ol>
<li>pip install 包名 - 卸载: pip uninstall 包名</li>
<li>pip install 下载的whl包.whl</li>
<li>pip install -r requiements.txt(安装requirements.txt中的所有依赖包)</li>
<li>pip list 查看已安装的三方包,pip freeze 已文件格式显示已安装的三方包(用于导出requiremnts.txt文件)</li>
</ol>
</li>
<li>源码安装
<ol>
<li>下载源码包,解压,进入解压目录</li>
<li>打开命令行,执行 <code>python setup.py install</code></li>
<li>验证:进入python shell,输入import 包名,不报错表示安装成功</li>
</ol>
</li>
<li>三方包默认安装路径:Python3.6.5/Lib/site-packages/ 下</li>
</ol>
<h3 id="python基本语法">Python基本语法</h3>
<ol>
<li>缩进</li>
</ol>
<pre><code>if x &gt; 0:
    print("正数")
elif x = 0:
    print("0")
else:
    print("负数")

def add(x,y):
    return x+y
</code></pre>
<ol start="2">
<li>一行多条语句</li>
</ol>
<pre><code>x=1; y=2; print(x+y)
</code></pre>
<ol start="3">
<li>断行</li>
</ol>
<pre><code>print("this line is too long, \
so I break it to two lines")
</code></pre>
<ol start="4">
<li>注释</li>
</ol>
<pre><code># 单行注释
a = 1

'''这是一段
多行注释'''

def add(x, y):
    """加法函数:这是docstring(函数说明)"""
    pass
</code></pre>
<ol start="5">
<li>变量
<ol>
<li>变量类型(局部变量、全局变量、系统变量)</li>
<li>变量赋值
<ul>
<li>多重赋值<code>x=y=z=1</code></li>
<li>多元赋值<code>x,y = y,x</code></li>
</ul>
</li>
<li>变量自增 <code>x+=1</code> <code>x-=1</code>(不支持<code>x++</code>, <code>x--</code>)</li>
</ol>
</li>
</ol>
<blockquote>
<p>Python3中没有常量</p>
</blockquote>
<h3 id="基本数据类型6种">基本数据类型(6种)</h3>
<h4 id="1-数字number">1. 数字Number</h4>
<ol>
<li>种类
<ol>
<li>整型int(Python3中没有长整型,int长度几乎没有限制)</li>
<li>浮点型float</li>
<li>布尔型bool
<ul>
<li>False: 0,0.0,'',[],(),{}</li>
<li>True: 除False以外,['']或[[],[]]不是False</li>
</ul>
</li>
<li>复数型complex</li>
</ol>
</li>
<li>操作符: +,-,*,/,//(地板除),**(乘方) - Python3中的/是真实除,1/2=0.5</li>
<li>类型转
<ol>
<li>str(): 其他类型转为字符串, 如<code>str(12)</code></li>
<li>int(): 字符串数字转为整型(字符串不是纯整数会报错), 如<code>int("12")</code></li>
<li>float(): 字符串转换为浮点数,如<code>float("1.23")</code></li>
</ol>
</li>
</ol>
<h4 id="2-字符串string">2. 字符串String</h4>
<ol>
<li>
<p>字符串系统方法</p>
<ul>
<li>len(): 计算字符串长度,如<code>len("abcdefg")</code></li>
<li>find()/index(): 查找字符串中某个字符第一次出现的索引(index()方法查找不到会报错), 如<code>"abcdefg".find("b"); "abcedfgg".index("g")</code></li>
<li>lower()/upper(): 将字符串转换为全小写/大写,如<code>"AbcdeF".lower();"abcedF".upper()</code></li>
<li>isdigit()/isalpha()/isalnum(): 判断字符串是否纯数字/纯字母/纯数字字母组合, 如<code> isdigit("123")</code>,结果为 True</li>
<li>count(): 查询字符串中某个元素的数量,如<code>"aabcabc".count("a")</code></li>
<li>join(): 将列表元素按字符串连接,如<code>"".join(["a","b","c"])</code>会按空字符连接列表元素,得到"abc"</li>
<li>replace(): 替换字符串中的某已部分,如<code>"hello,java".replace("java", "python")</code>,将java 替换为 python</li>
<li>split(): 和join相反,将字符串按分隔符分割成列表, 如<code>"a,b,c,d".split(",")</code>得到["a", "b", "c", "d"]</li>
<li>strip()/lstrip()/rstrip(): 去掉字符串左右/左边/右边的无意字符(包括空格,换行等非显示字符),如<code>" this has blanks \n".strip()</code>得到"this has balnks"</li>
</ul>
</li>
<li>
<p>字符串格式化</p>
<ul>
<li>%: 如<code>"Name: %s, Age: %d" % ("Lily", 12)</code>或<code>"Name: %(name)s, Age: %(age)d" % {"name": "Lily", "age": 12}</code></li>
<li>format: 如<code>"Name: {}, Age: {}".format("Lily", 12)</code>或<code>"Name: {name}, Age: {age}".format(name="Lily",age=12)</code></li>
<li>substitude(不完全替换会报错)/safe_substitude: 如<code>"Name: ${name}, Age: ${age}".safe_substitude(name="Lily",age=12)</code></li>
</ul>
</li>
<li>
<p><em>案例</em>: 利用format生成自定义html报告</p>
<p>tpl='''</p>
<title>{title}</title>

<h1>{title}</h1>

   {trs}
<table border="1px">
   <tbody><tr>
         <th>序号</th>
         <th>用例</th>
         <th>结果</th>
   </tr></tbody></table>


'''
<p>tr='''{sn}</p>
{case_name}
{result}
'''
<p>title="自动化测试报告"<br>
case_results = [("1", "test_add_normal", "PASS"),("2", "test_add_negative", "PASS"), ("3", "test_add_float", "FAIL")]</p>
<p>trs=''<br>
for case_result in case_results:<br>
tr_format = tr.format(sn=case_result, case_name=case_result, result=case_result)<br>
trs += tr_format</p>
<p>html = tpl.format(title=title, trs=trs)</p>
<p>f = open("report.html", "w")<br>
f.write(html)<br>
f.close()<br>
结果预览</p>
</li>
</ol>
<h1>自动化测试报告</h1>
<table>
<thead>
<tr>
<th>序号</th>
<th>用例</th>
<th>结果</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>test_add_normal</td>
<td>PASS</td>
</tr>
<tr>
<td>2</td>
<td>test_add_negative</td>
<td>PASS</td>
</tr>
<tr>
<td>3</td>
<td>test_add_float</td>
<td>FAIL</td>
</tr>
</tbody>
</table>
<h4 id="3-列表list">3. 列表List</h4>
<blockquote>
<p>列表元素支持各种对象的混合,支持嵌套各种对象,如<code>["a", 1, {"b": 3}, ]</code></p>
</blockquote>
<ol>
<li>列表操作
<ul>
<li>赋值: <code>l = </code></li>
<li>获取: <code>a = l # 通过索引获取</code></li>
<li>增: <code>l.append("c");l.extend(["d","e"]);l+["f"]</code></li>
<li>删: <code>l.pop() # 按索引删除,无参数默认删除最后一个;l.remove("c") # 按元素删除</code></li>
<li>改:<code>l="HELLO" # 通过索引修改</code></li>
<li>查: 遍历 <code>for i in l: print(i)</code></li>
</ul>
</li>
<li>列表系统方法
<ul>
<li>append()/insert()/extend(): 添加/插入/扩展(连接)</li>
<li>index(): 获取元素索引</li>
<li>count(): 统计元素个数</li>
<li>pop()/remove(): 按索引/元素删除</li>
<li>sort()/reverse(): 排序/反转</li>
<li><em>案例</em>: 字符串反转<code>s="abcdefg"; r=''.join(reversed(a))</code></li>
</ul>
</li>
</ol>
<h4 id="4-元组tuple">4. 元组Tuple</h4>
<ol>
<li>不可改变,常用作函数参数(安全性好)</li>
<li>同样支持混合元素以及嵌套</li>
<li>只有一个元素时,必须加","号,如<code>a=("hello",)</code> - 因为Python中()还有分组的含义,不加","会识别为字符串</li>
</ol>
<blockquote>
<p>字符串/列表/元组统称为序列, 有相似的结构和操作方法</p>
</blockquote>
<h3>序列相关操作方法</h3>
1. 索引
    - 正反索引: ```l;l[-1]```
    - 索引溢出(IndexError): 当索引大于序列的最大索引时会报错,如最大索引是3,引用l会报IndexError
2. 切片
    - l # 从列表索引1到索引3(不包含索引3)进行截取, 如 l = , l为
    - l[:5:2] # 第一个表示开始索引(留空0), 第二个表示结束索引(留空为最后一个,即-1), 第三个是步长, 即从开头到第5个(不包含第5个),跳一个取一个
    - *案例*: 字符串反转 ```s="abcdefg";r=s[::-1]```
3. 遍历
    - 按元素遍历: ```for item in l: print(item)```
    - 按索引遍历: ```for index in range(len(l)): print(l)```
    - 按枚举遍历: ```for i,v in enumerate(l): print((i,v))```
4. 扩展/连接(添加多个元素): extend()/+```"abc"+"123";+;.extend()```
5. 类型互转: str()/list()/tuple()
&gt;list转str一般用join(), str转list一般用split()
<ol start="6">
<li>系统函数
<ul>
<li>len(): 计算长度</li>
<li>max()/min(): 求最大/最小元素</li>
<li>sorted()/reversed(): 排序/反转并生成新序列(sort()/reverse()直接操作原序列)<code>l_new=sorted(l);l_new2=reversed(l)</code></li>
</ul>
</li>
</ol>
<h4 id="5-集合set">5. 集合Set</h4>
<ol>
<li>集合可以通过序列生成<code>a = set()</code></li>
<li>集合无序,元素不重复(所有元素为可哈希元素)</li>
<li>集合分为可变集合set和不可变集合frozenset</li>
<li>操作方法: 联合|,交集&amp;,差集-,对称差分^</li>
<li>系统函数: add()/update()/remove()/discard()/pop()/clear()</li>
<li><em>案例1</em>: 列表去重: <code>l=;l=list(set(l))</code> (由于集合无序,无法保持原有顺序)</li>
<li><em>案例2</em>: 100w条数据,用列表和集合哪个性能更好? - 集合性能要远远优于列表, 集合是基于哈希的, 无论有多少元素,查找元素永远只需要一步操作, 而列表长度多次就可能需要操作多少次(比如元素在列表最后一个位置)</li>
</ol>
<h4 id="6-字典dict">6. 字典Dict</h4>
<ol>
<li>字典是由若干key-value对组成, 字典是无序的, 字典的key不能重复,而且必须是可哈希的,通常是字符串</li>
<li>字典操作
<ul>
<li>赋值: <code>d = {"a":1, "b":2}</code></li>
<li>获取: <code>a = d['a']</code>或<code>a = d.get("a") # d中不存在"a"元素时不会报错</code></li>
<li>增: <code>d["c"] = 3; d.update({"d":5, "e": 6}</code></li>
<li>删: <code>d.pop("d");d.clear() # 清空</code></li>
<li>查: <code>d.has_key("c")</code></li>
<li>遍历:
<ul>
<li>遍历key: <code>for key in d:</code>或<code>for key in d.keys():</code></li>
<li>遍历value: <code>for value in d.values():</code></li>
<li>遍历key-value对: <code>for item in d.items():</code></li>
</ul>
</li>
</ul>
</li>
<li><em>案例</em>: 更新接口参数 api = {"url": "/api/user/login": data: {"username": "张三", "password": "123456"}},将username修改为"李四"<br>
<code>api['data']['username'] = "李四"</code> 或 <code>api['data'].update({"username": "李四"})</code></li>
</ol>
<blockquote>
<p>哈希与可哈希元素</p>
</blockquote>
<ol>
<li>哈希是通过计算得到元素的存储地址(映射), 这就要求不同长度的元素都能计算出地址,相同元素每次计算出的地址都一样, 不同元素计算的地址必须唯一, 基于哈希的查找永远只需要一步操作, 计算一下得到元素相应的地址, 不需要向序列那样遍历, 所以性能较好</li>
<li>可哈希元素: 为了保证每次计算出的地址相同, 要求元素长度是固定的, 如数字/字符串/只包含数字,字符串的元组, 这些都是可哈希元素</li>
</ol>
<blockquote>
<p>6种类型简单的特点总结</p>
</blockquote>
<ol>
<li>数字/字符串/元祖: 长度固定</li>
<li>序列(字符串/列表/元祖): 有序</li>
<li>集合/字典: 无序, 不重复/键值不重复</li>
</ol>
<h3 id="条件循环">条件/循环</h3>
<h4 id="条件判断">条件判断</h4>
<ol>
<li>示例:</li>
</ol>
<pre><code>if x&gt;0:
    print("正数")
elif x=0:
    print("0")
else:
    print("负数")
</code></pre>
<ol start="2">
<li>
<p>三元表达式: <code>max = a if a &gt; b else b</code></p>
</li>
<li>
<p><em>案例</em>: 判断一个字符串是不ip地址</p>
<p>ip_str = '192.168.100.3'<br>
ip_list = ip_str.split(".") # 将字符串按点分割成列表<br>
is_ip = True # 先假设ip合法<br>
if len(ip_list) != 4:<br>
is_ip= False<br>
else:<br>
for num in ip_list:<br>
if num.lstrip('0')!=num or not isdigit(num) or not 0 &lt;= int(num) &lt;= 255:<br>
is_ip = False<br>
if is_ip:<br>
print("是ip")<br>
else:<br>
print("不是ip")</p>
</li>
</ol>
<blockquote>
<p>使用map函数的实现方法(参考):</p>
</blockquote>
<p>defcheck_ipv4(ip_str):<br>
ip = ip_str.strip().split(".")<br>
return len(ip)<mark>4 and all(map(lambda x: x.lstrip('0')</mark>x and x.isdigit() and 0&lt;=int(x)&lt;= 255, ip))</p>
<h4 id="循环">循环</h4>
<ol>
<li>for in 循环</li>
<li>while 循环</li>
</ol>
<h3 id="文件读写文本文件">文件读写(文本文件)</h3>
<blockquote>
<p>html/xml/config/csv也可以按文本文件处理</p>
</blockquote>
<h4 id="文件操作方法">文件操作方法</h4>
<ol>
<li>open(): 打开<code>f =open("test.txt")</code>或<code>f =open("test.txt","r", encoding="utf-8")</code>或<code>with open("test.txt) as f: # 上下文模式,出结构体自动关闭文件</code></li>
<li>read()/readline()/readlines(): 读取所有内容/读取一行/读取所有行(返回列表) - 注意: 内容中包含\n换行符,可以通过strip()去掉</li>
<li>f.write()/f.save(): 写文件/保存文件</li>
<li>f.seek(): 移动文件指针,如f.seek(0), 移动到文件开头</li>
<li>f.close(): 关闭文件(打开文件要记得关闭)</li>
</ol>
<h4 id="文件打开模式">文件打开模式</h4>
<ol>
<li>r/w/a: 只读/只写/追加模式</li>
<li>rb/wb/ab: 二进制只读/只写/追加模式(支持图片等二进制文件)</li>
<li>r+/rb+, w+/wb+, a+/ab+: 读写,区别在于, r+/w+会清空文件再写内容, r+文件不存在会报错, a+不清空原文件,进行追加, w+/a+文件不存在时会新建文件</li>
</ol>
<blockquote>
<p>文件是可迭代的,可以直接用 for line in f: 遍历</p>
</blockquote>
<h3 id="函数类">函数/类</h3>
<h4 id="函数定义和调用">函数定义和调用</h4>
<pre><code>def add(x, y): # 定义函数
    return x+y

print(add(1,3)) # 调用函数
</code></pre>
<p><em>案例</em>: 用户注册/登录函数</p>
<pre><code>users = {"张三": "123456"}

def reg(username, password):
    if users.get(username): # 如果用户中存在username这个key
      print("用户已存在")
    else:
      users = password # 向users字典中添加元素
      print("添加成功")

def login(username, password)
    if not users.get(username):
      print("用户不存在")
    elif users['username'] == password:
      print("登录成功")
    else:
      print("密码错误")
</code></pre>
<h4 id="参数和返回值">参数和返回值</h4>
<ol>
<li>函数没有return默认返回None</li>
<li>参数支持各种对象,包含数字,支付串,列表,元组,也可以是函数和类</li>
<li>参数默认值: 有默认值的参数必须放在最后面, 如```def add(x, y=1, z=2):</li>
<li>不定参数: *args和**kwargs, 如<code>def func(*args, **kwargs):</code>可以接受任意长度和格式的参数</li>
<li>参数及返回值类型注释(Python3)</li>
</ol>
<pre><code>def(x:int, y:int) -&gt; int: # x,y为int型,函数返回为int型,只是注释,参数格式非法不会报错
    return x+y
</code></pre>
<h4 id="函数作为参数如-装饰器">函数作为参数(如: 装饰器)</h4>
<pre><code>def a():
    print("I'm a")
def deco(func):
    print("call from deco")
    func()

deco(a) # 输出"call from deco"并调用a(),输出"I'm a"
</code></pre>
<h4 id="函数嵌套支持闭包">函数嵌套(支持闭包)</h4>
<pre><code>def a():
    a_var = 1
    def b:() # 嵌套函数
      a_var += 1
</code></pre>
<h4 id="函数递归自己调用自己直到满足需求">函数递归(自己调用自己,直到满足需求)</h4>
<p><em>案例</em>: 求N!</p>
<pre><code>def factorial(n):
    return 1 if n == 0 or n == 1 else n * factorial(n-1)
</code></pre>
<h3 id="模块包">模块/包</h3>
<h4 id="模块">模块</h4>
<ol>
<li>一个py文件为一个模块</li>
<li>模块导入
<ul>
<li>import os # 需要通过os调用相关方法, 如os.mkdir(),</li>
<li>form configparser import ConfigParser: 可以直接使用CinfigParser()</li>
<li>支持一次导入多个</li>
</ul>
</li>
</ol>
<h4 id="包">包</h4>
<ol>
<li>一个文件夹为一个包(Python3,文件夹中不需要建立__init__.py文件)</li>
</ol>
<h4 id="常用系统模块">常用系统模块</h4>
<ol>
<li>os: 与操作系统交互
<ul>
<li>os.name/os.sep/os.linesep: 系统名称/系统路径分隔符/系统换行符</li>
<li>os.makedir()/os.makedirs(): 建立目录/建立多级目录</li>
<li>os.getenv("PATH"): 获取系统PATH环境变量的设置</li>
<li>os.curdir/os.prdir: 获取当前路径/上级路径</li>
<li>os.walk(): 遍历文件夹及子文件</li>
<li>os.path.basename()/os.path.abspath()/os.path.dirname(): 文件名/文件绝对路径/文件上级文件夹名</li>
<li>os.path.join()/os.path.split(): 按当前系统分隔符(os.sep)组装路径/分割路径</li>
<li>os.path.exists()/os.path.isfile()/os.path.isdir(): 判断文件(文件夹)是否存在/是否文件/是否文件夹</li>
<li><em>案例</em>: 用例发现, 列出文件夹及子文件夹中所有test开头的.py文件,并输出文件路径</li>
</ul>
</li>
</ol>
<pre><code>for root,dirs,files in os.walk("./case/"):
    for file in files:
      if file.startswith("test") and file.endswith(".py"):
            print(os.path.join(root, file)
</code></pre>
<ol start="2">
<li>sys: 与Python系统交互
<ul>
<li>sys.path: 系统路径(搜索路径)</li>
<li>sys.platform: 系统平台,可以用来判断是python2还是3</li>
<li>sys.argv: py脚本接受的命令行参数</li>
<li>sys.stdin/sys.stdout/sys.stderr: 标准输入/输出/错误</li>
</ul>
</li>
</ol>
<h3 id="常见算法">常见算法</h3>
<h4 id="冒泡排序">冒泡排序</h4>
<pre><code>def buddle_sort(under_sort_list):
    l = under_sort_list
    for j in range(len(l)):
      for i in range(len(l)-j-1):
         if l &gt; l:
                l, l = l, l
</code></pre>
<h4 id="快速排序">快速排序</h4>
<pre><code>def quick_sort(l):
    if len(l) &lt; 2:
      return l # 如果列表只有一个元素, 返回列表(用于结束迭代)
    else:
      pivot =l # 取列表第一个元素为基准数
      low = if i &lt; pivot] # 遍历l, 将小于基准数pivot的全放入low这个列表
      high = if i &gt;= pivot ]
      return quick_sort(low) + + quick_sort(high) # 对左右两部分分别进行迭代
</code></pre>
<h4 id="二分查找">二分查找</h4>
<pre><code>def bin_search(l, n): # l为有序列表
    low, high = 0, len(l) - 1 # low,high分别初始化为第一个/最后一个元素索引(最小/最大数索引)
    while low &lt; high:
      mid = (high-low) // 2 # 地板除,保证索引为整数
      if l == n:
            return mid
      elif l &gt; n: # 中间数大于n则查找前半部分, 重置查找的最大数
            high = mid -1
      else: # 查找后半部分, 重置查找的最小数
            low = mid + 1
    return None# 循环结束没有return mid 则说明没找到
</code></pre>
<blockquote>
<p>作业</p>
</blockquote>
<ol>
<li>查找文件中最长的行</li>
<li>统计文件中字符个数</li>
<li>判断字符串"abacdbdde"中第一个不重复的字符</li>
<li>判断字符串"{{({()[({})])}}"是否括号全部闭合</li>
</ol><br><br>
来源:https://www.cnblogs.com/superhin/p/12737646.html
頁: [1]
查看完整版本: Python接口测试课程(第一天)-Python基础