据科学家比软件工程师擅长统计,又比统计学家擅长软件工程。听起来牛逼轰轰,事实却是,许多数据科学家有统计学背景,却没有什么软件工程方面的经验,因此在编码时容易犯一些简单的错误。作为一名高级数据科学家,本文作者总结了他在工作中常见数据科学家犯的十大错误。
我是一名高级数据科学家,在 Stackoverflow 的 python 编码中排前 1%,而且还与众多(初级)数据科学家一起工作。下文列出了我常见到的 10 个错误。
没有共享代码中引用的数据
数据科学需要代码和数据。所以为了让其他人能够复现自己做出来的结果,你需要提供代码中涉及的数据。这看起来很简单,但许多人会忘记共享代码中需要的数据。
import pandas as pd df1=pd.read_csv('file-i-dont-have.csv') # fails do_stuff(df)
解决方案:用 d6tpipe 共享代码中的数据文件,或者将数据文件上传到 S3/网页/Google 云等,还可以将数据文件保存到数据库中,以便收件人检索文件(但不要将数据添加到 git 中,这一点后面的内容会讲到)。
硬编码其他人无法访问的路径
和错误 1 类似,如果硬编码其他人无法访问的路径,他们就没法运行你的代码,而且在很多地方都必须要手动修改路径。Booo!
import pandas as pd df=pd.read_csv('/path/i-dont/have/data.csv') # fails do_stuff(df) # or impor os os.chdir('c:\\Users\\yourname\\desktop\\python') # fails
解决方案:使用相对路径、全局路径配置变量或 d6tpipe,这样其他人就可以轻易访问你的数据了。
将数据和代码混在一起
既然数据科学代码需要数据,为什么不将代码和数据存储在同一个目录中呢?但你运行代码时,这个目录中还会存储图像、报告以及其他垃圾文件。乱成一团!
├── data.csv ├── ingest.py ├── other-data.csv ├── output.png ├── report.html └── run.py
解决方案:对目录进行分类,比如数据、报告、代码等。参阅 Cookiecutter Data Science 或 d6tflow 项目模板,并用问题 1 中提到的工具存储以及共享数据。
用 Git 提交数据
大多数人现在都会版本控制他们的代码(如果你没有这么做那就是另一个问题了!)。在共享数据时,可能很容易将数据文件添加到版本控制中。对一些小文件来说这没什么问题。但 git 无法优化数据,尤其是对大型文件而言。
git add data.csv
解决方案:使用问题 1 中提到的工具来存储和共享数据。如果你真的需要对数据进行版本控制,请参阅 d6tpipe、DVC 和 Git Large File Storage。
写函数而不是 DAG
数据已经讨论得够多了,接下来我们谈谈实际的代码。你在学编程时,首先学的就是函数,数据科学代码主要由一系列线性运行的函数组成。这会引发一些问题,详情请参阅「4 Reasons Why Your Machine Learning Code is Probably Bad。」
def process_data(data, parameter): data=do_stuff(data) data.to_pickle('data.pkl') data=pd.read_csv('data.csv') process_data(data) df_train=pd.read_pickle(df_train) model=sklearn.svm.SVC() model.fit(df_train.iloc[:,:-1], df_train['y'])
解决方案:与其用线性链接函数,不如写一组有依赖关系的任务。可以用 d6tflow 或者 airflow。
写 for 循环
和函数一样,for 循环也是你在学代码时最先学的。这种语句易于理解,但运行很慢且过于冗长,这种情况通常表示你不知道用什么替代向量化。
x=range(10) avg=sum(x)/len(x); std=math.sqrt(sum((i-avg)**2 for i in x)/len(x)); zscore=[(i-avg)/std for x] # should be: scipy.stats.zscore(x) # or groupavg=[] for i in df['g'].unique(): dfg=df[df[g']==i] groupavg.append(dfg['g'].mean()) # should be: df.groupby('g').mean()
解决方案:NumPy、SciPy 和 pandas 都有向量化函数,它们可以处理大部分你觉得需要用 for 循环解决的问题。
没有写单元测试
随着数据、参数或者用户输入的改变,你的代码可能会中断,而你有时候可能没注意到这一点。这就会导致错误的输出,如果有人根据你的输出做决策的话,那么错误的数据就会导致错误的决策!
解决方案:用 assert 语句检查数据质量。Pandas 也有相同的测试,d6tstack 可以检查数据的获取,d6tjoin 可以检查数据的连接。检查数据的示例代码如下:
assert df['id'].unique().shape[0]==len(ids) # have data for all ids? assert df.isna().sum()<0.9 # catch missing values assert df.groupby(['g','date']).size().max()==1 # no duplicate values/date? assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # all ids matched?
没有注释代码
我明白你急着做分析。于是你把代码拼凑起来得到结果,把结果交给你的客户或者老板。一周之后他们找到你,问你「你能改掉 xyz 吗?」或「你能更新一下结果吗?」。然后你和自己的代码大眼瞪小眼,既不记得你为什么要这么做,也不记得你做过什么。现在想象一下其他人运行这段代码时的心情。
def some_complicated_function(data): data=data[data['column']!='wrong'] data=data.groupby('date').apply(lambda x: complicated_stuff(x)) data=data[data['value']<0.9] return data
解决方案:即便你已经完成了分析,也要花时间注释一下你做过什么。你会感谢自己的,当然其他人会更加感谢你!这样你看起来会更专业!
把数据存成 csv 或 pickle
说回数据,毕竟我们讨论的是数据科学。就像函数和 for 循环一样,CSV 和 pickle 文件也很常用,但它们其实并没有那么好。CSV 不包含模式(schema),所以每个人都必须重新解析数字和日期。Pickle 可以解决这一点,但只能用在 Python 中,而且不能压缩。这两种格式都不适合存储大型数据集。
def process_data(data, parameter): data=do_stuff(data) data.to_pickle('data.pkl') data=pd.read_csv('data.csv') process_data(data) df_train=pd.read_pickle(df_train)
解决方案:用 parquet 或者其他带有数据模式的二进制数据格式,最好还能压缩数据。d6tflow 可以自动将数据输出存储为 parquet,这样你就不用解决这个问题了。
使用 Jupyter notebook
这个结论还有一些争议——Jupyter notebook 就像 CSV 一样常用。很多人都会用到它们。但这并不能让它们变得更好。Jupyter notebook 助长了上面提到的许多不好的软件工程习惯,特别是:
Jupyter notebook 很容易上手,但规模太小。
解决方案:用 pycharm 和/或 spyder。
原文链接:https://medium.com/m/global-identity?redirectUrl=https%3A%2F%2Ftowardsdatascience.com%2Ftop-10-coding-mistakes-made-by-data-scientists-bb5bc82faaee
要:本次分享主要介绍 Hive数据如何迁移到MaxCompute。MMA(MaxCompute Migration Assist)是一款MaxCompute数据迁移工具,本文将为大家介绍MMA工具的功能、技术架构和实现原理,再通过实际操作MMA,演示将Hive数据迁移到MaxCompute。
演讲嘉宾简介:阿里云智能产品专家-云花
精彩视频回顾:Hive数据如何同步到MaxCompute
以下内容根据演讲视频以及PPT整理而成。本次分享主要围绕以下两个方面:一、MMA功能介绍、技术架构和原理二、MMA数据迁移操作演示
一、MMA功能介绍、技术架构和原理1.MMA功能介绍MMA主要覆盖的场景包括批处理,存储,数据集成,作业编排及调度。MMA提供迁移评估分析功能,自动化生成迁移评估报告。迁移评估报告会报告出从Hive表的数据结构到MaxCompute的数据结构之间是否有数据类型映射兼容性问题,如语法问题。MMA支持自动化数据迁移功能,支持批量建表以及数据自动化批量迁移。另外,MMA还支持作业语法分析,可以检查Hive SQL能否直接运行在MaxCompute里。MMA还支持工作流迁移,对主流数据集成工具Sqoop进行作业的迁移转换,并自动创新DataWorks数据继承作业。
2.MMA迁移服务架构MMA迁移服务架构如下图。左侧是客户Hadoop集群,右侧的是Aliyun 大数据服务,主要是DataWorks和MaxCompute。MMA工具会跑在客户的Hadoop集群上,客户的服务器需要能够访问Hive Server。在机器上部署MMA客户端工具时会自动化获取Hive Meta里的数据,既将Hive的Meta数据从MySQL中读出来,还可以将Meta信息自动转换成MaxCompute DDL,然后用DDL在MaxCompute中批量创建表,批量拉起数据同步的作业,向Hive Server并发提交Hive SQL作业。基于Hive SQL作业调用一个UDF,UDF里面会集成Tunnel的SDK,基于Tunnel将数据批量写到MaxCompute的表中。作业和工作流的迁移也是基于MMA客户端工具自动发现的Hive Meta数据,做工作流的作业检查,包括把工作流的组件中的工作流的配置批量转换成DataWorks工作流的配置,直接生成DataWorks工作流。以上步骤完成了数据到作业到工作流的迁移。最后一步是迁移完成后需要基于MaxCompute和DataWorks架构对接业务系统。
3.MMA Agent技术构架和原理通过客户端和服务端,MMA可支持数据和工作流的批量迁移。安装在客户服务器上的MMA客户端工具包含下图中的四个能力。首先可自动获取Hive Metadata,并自动创建生成DDL和UDTF,而且可批量创建表和批量Hive数据迁移。相应的,MMA有四个主要组件。Meta Carrier工具自动将Hive Meta信息提取出来,在本地生成Hive Meta结构。Meta Processor是基于Meta Carrier工具产出的结果,基于Hive Meta数据批量转成MaxCompute的DDL,既批量转成建表语句和数据类型的转换。此外,MMA客户端工具还内置了ODPS Console,基于ODPS Console将Meta Processor产出的ODPS DDL在MaxCompute上批量创建表。最后基于Data Carrier批量创建Hive SQL作业。每个Hive SQL作业相当于多个表或者多个分区并行的数据的同步。
二、MMA数据迁移操作演示1.环境准备如下图所示,MMA环境运行要求是jdk1.6版本以上,Python3+。另外,运行MMA的机器,通过Hive Client提交Hive SQL的作业。机器还需要可以访问Hive Server,并连接MaxCompute服务。下图右侧的场景案例是客户在基于MMA做同步数据时发现的问题。例子中客户有自己的IDC,在阿里云有自己的ECS,客户从IDC拉一条专线访问阿里云。在安装MMA之前,客户可以从ECS上直接访问MaxCompute,但IDC里的机器不能访问MaxCompute。此时需要在这条专线上增加VBR路由配置,既在边界路由上增加一个配置。配置之后可以打通从IDC到ECS,甚至到MaxCompute服务的网络访问。
2.下载和编译工具包下载编译工具包有两种方法。一是下载下图中编译好的工具包。此外,由于用户的Hive版本各不相同,用户可以根据MMA官网上提供的GitHub地址下载源码,拉到本地进行编译。
3.MMA Agent操作说明使用meta-carrier采集Hive Metadata:机器提前安装好Hadoop环境,本地有Hive Server。提前下载客户端的odps-data-carrier.zip包,并在本地解压。解压完成后会显示下图所示目录。bin目录下有几个文件,首先是MMA的几个核心角色:meta-carrier、meta-processor、odps_ddl_runner用于批量创建表,hive_udtf_sql_runner用于同步数据。libs目录下是工具依赖的jar包和库。 res目录的console目录下的bin目录包含odpscmd,是MMA客户端的工具,odps_config,ini配置文件。本地Hive上面有三个库,其中dma_demo库下有五个表,可将五个表自动批量同步到MaxCompute上。首先需要在MaxCompute上创建一个project,既在DataWorks控制台创建一个空Project。打开新的命令窗口,在本地运行的ODPS Command客户端工具,连接新创建的空的project。在已经安装了MMA Hive的机器上运行,解压,进入odps-data-carrier工具的目录。执行 bin/meta-carrier -h查看其参数说明,-d表示用户可以指定数据库,通过指定数据库提取meta数据,若不指定,会将Hive下所有的库的meta都拉取出来。-o指定输出目录,-t参数指定表,-u参数指定uri地址,即Hive Meta的地址。开始测试时首先指定地址,因为是thirft地址,所以用thirft协议连接。此外由于Hive Meta在本地,所以只需要将dma_demo库的meta拉取出来,加-o参数,指定目录。通过tree meta可以查看meta目录结构。meta目录下生成和数据库同名的dma_demo目录。dma_demo目录下的json文件是描述数据库meta信息的文件。partition_meta里面的两个表是分区表,table_meta的表是非分区表,会把所有表集的meta信息写在下面。
使用network-measurement-tool:网络测量工具network-measurement-tool用于网络测速,测量Hive集群到MaxCompute各region的网络连通质量。通过网络测速可以知道网络传输速度和大概的数据量,根据网络传输速度预估数据传输时间。network-measurement-tool工具连接MaxCompute上所有region的节点ENDPOINT地址,由最快到最慢做测速排序。下图中执行结果最快的是HANGZHOU,连接时间为51ms,最慢的是一个海外region KUALA_LUMPUR,连接时间为3393ms。
使用sql-checker检查Hive SQL是否可以直接在MaxCompute上执行:sql-checker可用于检查Hive SQL语法兼容性,判断SQL能否直接在MaxCompute上运行。其参数input要指定meta目录,指定缺省project和sql参数。若执行结果返回其兼容性OK,即此sql语句可以直接在MaxCompute上运行。
使用meta-processor生成ODPS DDL和Hive UDTF SQL:通过第一步已经拉出了Hive Meta库的metadata信息。下一步需要将Hive Meta转换成MaxCompute DDL。使用bin/meta-processor -h查看参数。-i即input,-o是output目录。bin/meta-processor的-i就是第一个命令的输出结果,代表meta的目录,存放的是carrier拉出的Hive Meta数据。指定-i meta -o output。将bin/meta-processor运行结果放入output中。生成output目录。tree output可查看结构。output目录下也会生成一个以MaxCompute的project命名的dma_demo目录。dma_demo目录下面有一个hive_udtf_sql目录,目录下面的.sql用于批量数据迁移。还包含odps_ddl目录,用于后续批量创建表,目录下的.sql是创建表的语句。
使用odps_ddl_runner.py批量创建表和分区:既然DDL已经生成,下一步需要批量创建表。批量创建表依赖MaxCompute的命令行工具(客户端工具)。工具包一级目录下的odps_config包含几个基本参数,其中project_name、access_id、access_key、end_point为必填项。配置完成可以开始批量创建表。批量创建表工具要执行Python命令,python36 bin/odps_ddl_runner.py -h。参数中input参数由meta processer自动生成,odpscmd参数不是必须指定的,它会默认找到所在目录,不需要单独配置参数。创建表过程要拉起odps_command工具,基于客户端工具来向MaxCompute提交建表语句。通过show table查看是否创建了五个表,再查看分区是否也建好。若Hive和MaxCompute上的分区创建完成,两边的表结构也应相同。
使用hive_udtf_sql_runner.py迁移数据:通过命令行python36 bin/hive_udtf_sql_runner.py开始读output目录下的.sql语句。查看python36 bin/hive_udtf_sql_runner.py命令的参数,Input_all会批量迁移output下所有数据。若只想做单表的迁移或者单分区的迁移,需要使用input_single_file参数。parallelism参数表示并行度。数据迁移完成后在MaxCompute中查看表中是否有数据。对比MaxCompute中的数据和Hive中对应表的数据。若其size相同,Hive和MaxCompute中对应表的数据相同,说明已经完整迁移数据。
进阶功能1:仅生成指定的database或table的metadata:在生成meta时可以不生成整个数据库的meta,可以指定一个表,生成一个表的meta。Meta carrier 工具提供了抓取指定数据库可表的能力。
进阶功能2:进灵活的hive到MaxCompute映射:如果用户需要自定义MaxCompute上的表,可以更改命名,加前缀或后缀,修改自定义字段名。如可以修改MaxCompute DDL里的json文件实现表名或字段名的自定义。
进阶功能3:单表或单分区迁移:上面的例子中已经批量迁移五张表,通过drop table inventory,演示单分区迁移。首先若只需同步一个分区的数据,需要重新创建一张表。执行python36 bin/odps_ddl_runner.py创建表,指定其output目录,开始批量创建表。此时inventory表以及其五个分区已经创建完成。但创建的分区中没有数据,可指定其中一个分区,如第二个分区。通过使用input_single_file参数,指定具体分区的sql目录。可指定目录为output/dma_demo/hive_udtf_sql/single_partition/inventory_1.sql。执行完成后查看结果,对比在Hive上第二分区的数据和迁移进MaxCompute的单分区的数据,若两个单分区数据一致,则表示迁移完成。
4.使用DataWorks自动迁移数据和工作流MMA1.0版本还未将工作流迁移做成服务化功能,目前还是一个线下工具。客户需要根据下图模板生成相应目录。在做工作流迁移时,如果使用开源组件,可以按照模板将配置放到相应目录下。如果不使用开源组件,如自研的工作流调度编排服务,可基于标准化模板,按照模板的目录结构生成用户自己的工作流数据,打成zip包上传到DataWorks。目前MMA1.0还需要客户手动打包文件上传zip包,后台会进行自动解析并加载到DataWorks工作流。上传完成后,DataWorks服务会根据ODPS DDL 批量生成MaxCompute的table。MaxCompute表创建后,DataWorks服务会自动拉起DataX的数据同步任务,完成批量数据迁移。
下图是可配置的项目描述文件project.xml,其中project信息可以自定义。另外一个是工作流描述文件,workflow.xml中是工作流自定义的参数,用户可以通过编辑配置文件进行修改。
5.其他类型作业的迁移方案UDF、MR迁移:用户直接将jar包上传到MaxCompute上,开启2.0支持,开启对Hive兼容的flag。将Hive兼容的flag设置为true,再在MaxCompute下直接迁移Hive下的UDF和MR。需求注意不支持UDF,MR中直接访问文件系统,网络访问和外部数据源连接。外表迁移:原则上能结构化的数据尽量迁移到MaxCompute内部表。如果必须通过外表访问外部文件,建议先将数据从HDPS迁移到OSS或OTS,再在MaxCompute中创建外部表,实现对文件的访问。Spark作业迁移:MMA对开源Spark的语法完全兼容。用户只需要下载Spark On MaxCompute客户端,在编写Spark SQL时仅增加MaxCompute的连接参数,其它部分和Spark SQL的语法相同。
6.查看迁移评估报告创建MaxCompute DDL完成后,除了生成DDL会SQL以外,还会生成迁移评估报告report.html文件。迁移评估报告是一个兼容性报告,显示Hive表的数据结构和MaxCompute表的数据结构之间的映射关系是否有风险,并标识风险等级。另外会给出明细说明以及预警提示,如数据类型不兼容或语法不兼容等。用户在迁移之前可以查看此报告评估迁移风险。
查看更多:https://yqh.aliyun.com/detail/6648?utm_content=g_1000106727
上云就看云栖号:更多云资讯,上云案例,最佳实践,产品入门,访问:https://yqh.aliyun.com/
口测试【接口:系统与系统之间,组件与组件之间,数据传递交互的通道】
1.1接口概念:指的是系统或组件之间的交互点,通过这些交互点可以实现数据的交互;可分为硬件接口和软件接口;
服务器开了个口,客户端发送请求
1.2接口的类型:
①按协议划分:http、tcp、ip②按语言划分:C++、java、php
③按范围划分,系统之间的接口和程序内部的接口
系统之间的接口:多个内部系统之间的交互【用户系统、订单系统、商品系统】,内部系统与外部系统【支付系统】之间的交互
程序内部的接口:方法与方法之间,函数与函数之间【传入不同的数据,输出不同的值,叫接口函数】,模块与模块之间的交互
1.3接口测试的概念
接口测试:对系统或组件之间的接口进行测试,校验传递的数据正确性和逻辑依赖关系(淘宝先登录才能看订单,即使复制了订单的网页,但是未登录,复制的订单网页打开还是跳转登录界面。)的正确性。【校验数据的交换、传递和控制管理的过程,以及相互逻辑依赖关系。】
1.4接口测试原理【接口测试主要测试目标:服务器,功能测试:测试客户端】
1>怎么测?模拟客户端,向服务器发送请求
2>用什么测?工具:fiddler、postman、jmeter;代码:python+UnitTest框架+Requests框架
3>测试什么?测试服务器针对客户端请求,回应的响应数据是否与预期结果一致
1.5特点
①测试可以提前介入,提早发现bug,符合质量控制前移的理念
②可以发现一些页面操作发现不了的问题
③接口测试低成本高效益(底层的一个bug能够引发上层8个左右bug,接口测试可以实现自动化)
④不同于传统的单元测试,接口测试是从用户的角度对系统进行全面的检查
1.6实现方式
工具:fiddler、postman、jmeter;代码:python+UnitTest框架+Requests框架
1.7自动化接口测试
接口自动化测试:借助工具、代码,模拟客户端发送请求给服务器,借助断言自动判断 预期结果和实际结果是否一致。【是让程序或工具代替人工自动地完成对接口进行测试的一种过程】
(超文本传输协议,基于请求与响应模式的,应用层协议,也是互联网上应用最为广泛的一种协议)【端口是用来找到应用】
2.1 协议:就是规则。要求通信的双方必须严格遵守。
2.2 特点
①支持客户端/服务器模式 ②简单快速 ③灵活 ④无连接 ⑤无状态
2.3 URL(Uniform Resource Locator)统一资源定位符,是互联网上标准资源的地址。HTTP使用URL来建立连接和传输数据。
作用:在网络环境中,唯一的定义一个数据资源
2.4 URL语法格式(组成)【http:80;https:443】
http[协议] :// xxxxx[域名] : xxxx[端口:0~65535] / xxxxxx[资源路径] ? xx[k=value]&xx&x[查询参数]
协议:规定数据传输的方式
域名:在网络环境中找到主机 用://与协议分隔
端口(port)【常省略】:在网络主机上,标识一个进程(运行起来的应用程序) 本地主机用PID标识 用 :与域名分隔
资源路径:标识网络资源(文件、图片、音视频、变量.....) 用/与端口分隔
查询参数:参数传递给资源路径 用?与资源路径分隔,内部用&分隔
【当资源路径没有时,可以认为是“/”】
2.5 HTTP请求【请求包;请求报文】
1>作用:
客户端(app、浏览器),发送请求给服务器时,使用的协议--http请求协议
规定发送给服务器的数据传输的语法格式
2>整体格式
第一行:请求行:请求方法(空格)url(空格)协议版本
第二行:请求头:语法格式 【格式:key:value】
user-agent:描述发送端的本地浏览器类型
Content-Type:xxxx(描述请求体的数据类型)通常碰到form(表单类型)和json类型
空行:代表http请求头结束,请求体开始
请求体:请求发送时携带的数据。 数据类型(Content-Type)的值【post、put(相当于修改)有请求体,get、delete没有请求体】
3>fiddler抓包验证
先清空fiddler--访问网站--点开(一般第一条)请求--点击【raw】
4>请求行
http请求方法(大小写无所谓)【对应数据库增删改查】
GET:查询
POST:添加(常用在登录)
PUT:修改
DELETE:删除
5>请求头
语法格式:k:v
user-agent:产生请求浏览器类型
Content-Type:请求体数据类型
application/json:JSON数据格式(k:v)
application/x-www-form-urlencoded:form表单数据
6>请求体
数据值的组织形式,受Content-Type的值影响
k=v格式
get、delete方法没有请求体
post、put方法有请求体
2.6 HTTP响应
1>作用:服务器端,针对客户端发送的http请求,回发响应数据。 --http应答
规定回发给客户端的数据组织格式
2>整体格式【响应包;响应报文】
响应行(状态行):协议版本(空格)状态码(空格)状态描述【状态码和状态描述捆绑,状态码对应状态描述】
响应头:语法格式:k:v
Content-Type:描述响应体中数据类型
空行:代表响应头结束
响应体:绝大多数情况不为空(请求成功:回发数据,失败:回发错误数据)
数据类型受Content-Type值影响
3>状态码【有三位数字组成,第一个数字定义响应的类别】
1xx:指示信息--表示请求已接收,等待继续处理
**2xx:成功--表示请求已被成功接收、理解、接受:eg:200、201
3xx:重定向--待访问的资源,需求重新指定路径访问。【要完成请求必须进行更进一步的操作】
**4xx:客户端错误--请求有语法错误或请求无法实现 eg:404【请求文件不存在】/403【请求文件存在但拒绝被访问,也就是说没有权限访问】
5xx:服务器端错误--服务器未能实现合法的请求
4>状态码描述
一般与状态码唯一对应
5>响应头
语法格式:k:v
Content-Type:值为响应体的数据类型
Content-Length:响应体的大小【可不写,浏览器自动求取,一旦写,必须准确】
6>响应体(测试中的实际结果,预期结果从接口文档中来)
就是响应的消息体,数据可以是普通文本、XML、JSON、HTML源码
1>传统风格
对用户进行操作的相关接口,包括增删改查
操作 | 请求方式 | URL | 成功状态 |
查询某个用户 | GET/POST | http://127.0.0.1:8080/myweb/user/getUser?id=1 http://127.0.0.1:8080/myweb/user/getById?id=1 http://127.0.0.1:8080/myweb/getUserById?id=1 | 200 |
查询所有用户 | GET/POST | http://127.0.0.1:8080/myweb/user/getUserList http://127.0.0.1:8080/myweb/user/getUsers | 200 |
添加用户 | POST | http://127.0.0.1:8080/myweb/user/addUser | 200 |
修改用户 | POST | http://127.0.0.1:8080/myweb/user/updateUser | 200 |
删除用户 | GET/POST | http://127.0.0.1:8080/myweb/user/deleteUser?id=1 | 200 |
特点:
请求方法,只使用get和post即可
URL不唯一,不重复。同一个操作可以对应不同的URL
状态码的使用较单一。200最常见
2>RESTful风格接口【一种软件架构风格、设计风格,而不是标准,只是提供了一组设计原则和约束条件】
REST:即(Representational State Transfer)的缩写,词组翻译是“表现层状态转化”【同一URL,对应的方法不同,对应的操作也不同】,如果一个架构符合REST原则,就称它为RESTful架构。
操作 | 请求方式 | URL | 成功状态 |
查询某个用户 | GET | http://127.0.0.1:8080/myweb/users/1 | 200 |
查询所有用户 | GET | http://127.0.0.1:8080/myweb/users | 200 |
添加用户 | POST | http://127.0.0.1:8080/myweb/users | 201 |
修改用户 | PUT | http://127.0.0.1:8080/myweb/users/1 | 201 |
删除用户 | DELETE | http://127.0.0.1:8080/myweb/users/1 | 204 |
架构特点:
1.每一个URL代表一种资源;
2.客户端和服务器之间,传递这种资源的某种表现层;
3.客户端通过四个HTTP动词,对服务器端资源进行操作,实现“表现层状态转换”(数据的不同表现形式,图像、文字表现同一个数据对象)
4.接口之间传递的数据最常用格式为JSON。
5.1接口文档
1>接口文档:又称为API文档,一般是由开发人员所编写的,用来描述系统所提供接口信息的文档。大家都根据这个接口文档进行开发,并需要一直维护和遵守。
2>作用
1.能够让前端开发与后台开发人员更好的配合,提高工作效率。(有一个统一参考的文件)
2.项目选代或者项目人员更迭时,方便后期人员查看和维护
3.方便测试人员进行接口测试
【错误码:不是错误,与http状态码区分开,其实是状态码,描述状态】
形式:word文档形式、Excel表格式形式、pdf文档
基本信息:
Path:对应url里的资源路径(url前面的协议等在接口文档的系统信息里呈现)
Method:PUT/POST/DELETE/GET
接口描述:。。。。。
请求参数:
Headers(请求头):数据类型(k【Content-Type】:v【application/json】)
Body(请求体):实现该接口使用的数据以及对应类型。
返回数据(预期结果):成功和失败的状态码
状态码:200 成功:状态码200
错误码(自定义状态码):码值和描述信息 失败:错误码(自定义状态码)
5.2接口文档解析
接口文档的解析本质:从接口文档中,找出http请求所需要的数据信息,包括:
请求方法、URL【行里两个】、请求头(k:v)【Content-Type类型】、请求体【数据:数据类型的名字和类型】(行头体)、响应状态码、描述。
Eg:
请求体:{“数据类型的名字,建议复制文档里的不要用手敲”:“数据值,文档中不知道,可找开发要”}
Fiddler:
K:v是json类型数据
Raw项:方法、url、请求头、请求体
6.1为什么要写
1.防止测试点漏测、条理清晰
2.方便分配工作,评估工作量和时间
3.面试使用
6.2接口测试的测试点(测试维度)
6.3功能测试
手工测试中的单个业务模块,一般对应一个接口。
Eg: 登录业务-->登录接口
加入购物车业务-->加入购物车接口
支付业务-->支付接口
.........
借助工具、代码,绕开前端界面,组织接口所需要的数据,展开接口测试。
按照用户实际使用场景,梳理接口业务场景。
组织业务场景时,一般只需要做正向测试即可。(与手工一致)
一般建议用最少的用例覆盖最多的业务场景。
Eg:登录---搜索商品---加购物车---下单---支付---评价
6.4性能测试
1>响应时长:发送请求,服务器多久回发响应
2>吞吐量:当前的接口处理用户的请求事物数量
3>并发数:多个用户同时向接口发请求,比如淘宝秒杀
4>服务器资源利用率:CPU、内存、显卡、网络I/O、磁盘I/O
6.5浏览器开发者工具
浏览器的开发者工具:F12或右键检查打开--->Network--->一定要选择ALL--->关于登录,可以在网站界面输入好数据,点击登录按钮--->查看
点击Name下数据--->do_login(与登录按钮对应):
Headers【相当于HTTP响应,组织形式不一样,但是数据该有的都有】:
General:表示总则;包括请求URL、请求方法、状态码(Status Code)、IP地址和端口号(Remote Address)
Response Headers:表示响应头;数据以k:v形式组织
Request Headers:表示请求头;对应HTTP请求头里的信息;数据类型依然k:v形式
Query String Parameters:表示查询字符串参数,对应url后部分的查询参数
Form Data:表单数据;比如登录界面,这部分是登录界面输入的数据
Payload:有一个view source,是请求体的数据,可以直接复制json数据
Response【查看服务器响应返回的结果】
6.6安全测试
1>攻击安全:由专业安全测试工程师完成;
2>业务安全
①敏感数据是否加密:比如密码
②SQL注入:
输入用户名为:‘ or 1=1#,提示用户名格式错误,表示没有SQL注入的漏洞
③其他
6.7与手工测试区别
1>手工测试测写入到输入框中的数据是否正确。接口测试测参数对应的参数值是否正确,相当于k:v。
2>接口测试不单单针对参数值进行测试,还可以针对参数本身进行测试。比如测username本身,用uname:正确的用户名去测试,看看能否通过。
对于参数测:
①正向参数:
必选参数:所有的必填项都包含。
组合参数:所有的必填+任意一个或多个可选参数
全部参数:所有的必填+所有的可选参数
②反向参数:
多参:多出一个或多个必选参数(可以任意指定)
少参:缺少一个或者多个必选参数
无参:没有必选参数
错误参数:参数名输入错误
6.8接口测试文档要素
编号、用例名称(标题)、模块、优先级、预置条件、请求方法、URL、请求头、请求体(请求数据)、预期结果
URL列:写完整URL或者写{协议+域名}/文档里的path内容【path写明确,协议和域名可写成文字,以防后期协议和域名修改,就不用大篇幅修改】
登录里的用户名未注册就是不存在
3>数值部分和手工测试一样,参数是接口特有的。
用户名和密码为空不能想当然认为都是用户名或密码错误,要去实践。
登录的信息都是去数据库中比对,如果特殊字符等在数据库中不允许出现,就不用做此类反向测试。要在数据库中组织出不符合的数据,测开发在接收数据的时候,不能依托数据库,而是依托开发的代码有没有校验出来,不符合规范的手机号是否能登录成功。
总结:在接口测试用例中,对于k:v,考虑k的正反向,v保证正确;考虑v的正反向,k保证正确。
8.1分析测试点
Eg:针对“员工管理”业务场景:登录---添加员工---查询员工(看看是否添加成功)---修改员工---再次查询(看看修改成功)---删除员工---查询员工(看看是否删除)【相当于把多个模块接口串起来,用最少的用例尽可能的覆盖所有接口】
8.2添加用户【测校验的情况:正确、错误、重复】
请求方法:post
URL:
请求头:
请求体:
返回数据:
8.3查询员工【测校验的情况:正确、空值、错误值】
8.4修改员工
8.5删除员工
9.1开发者工具
Headers:请求方法、request URL、request headers中的content-type【代表数据类型,后面的utf可以不管】、Form data【请求体,k:v对】
Preview:返回数据中看不懂的字符,在preview里能找到
Response:看返回数据【汉字的转码在preview里】
9.2Postman使用
Postman:
Headers:填写content-type的k:v值
Body:下拉框选项选择content-type中的v项,然后填入请求体中的k:v对,是json就选择raw【原始】
Send完看响应数据,在body下,选择pretty,把html改成json,就可以看到返回的结果了
结果:
点击sava或ctrl+s,小红点就没有了
总体步骤:
**3.1断言响应状态码
选择:Status code:code is 200
详情:pm.test("Status code is 200", function () {
pm.response.to.have.status(200);
});
解释:
pm:代表postman的一个实例【类下面的一个对象】
test():是pm实例的一个方法。有两个参数
参数1:在断言成功后,给出的文字提示,可以修改。"Status code is 200"
参数2:匿名函数,function () {pm.response.to.have.status(200);}
function代表函数,后面应该放函数名,但是没有,所以是匿名函数;
response代表响应体,to.have应该有
整句话表示:postman的响应结果中应该包含状态码200
200是预期结果
断言的结果在Tests项下Test Results,看到PASS和Status code is 200【对应断言成功后的描述】
3.2断言响应体是否包含某个字符串
选择:Response body:Contains string
详情:pm.test("Body matches string", function () {
pm.expect(pm.response.text()).to.include("string_you_want_to_search");
});
解释:预期结果用返回体内的value值,推荐用message的value
3.3断言响应体是否等于某个字符串(对象)【json花括号括起来是对象,中括号括起来是数组】
选择:Response body:Is equal to a string
详情:pm.test("Body is correct", function () {
pm.response.to.have.body("response_body_string");
});
解释:通常data对应令牌数据会不停地改变,这个字符串是对返回的全部字符串进行判断,一旦有数据不停变化时,断言不通过。
**3.4断言JSON数据
选择:Response body:JSON value check
详情:pm.test("Your test name", function () {
var jsonData=pm.response.json();
pm.expect(jsonData.value).to.eql(100);
});
解释:
var jsonData=pm.response.json(); var jsonData用js语法定义一个变量;jsonData是变量名;pm.response.json()代表响应的json结果,就是响应的数据
pm.expect(jsonData.value).to.eql(100); 预期json结果值等于100相同,value对应响应体中的key
3.5断言相应头【返回的Headers里】
选择:Response headers:Content-Type header check
详情:pm.test("Content-Type is present", function () {
pm.response.to.have.header("Content-Type");
});
解释:响应头中包含Content-Type;可以判定k:v是否正确,断言响应头所对应的value,直接(k,v)
示例:pm.test("Content-Type is present", function () {
pm.response.to.have.header("Content-Type","application/json");
});【在响应的headers中,添加响应头中的key对应的value判定,用,分隔】
15.1概念
全局变量:全局变量是全局唯一的,不可重复定义的变量
环境变量:一个变量只能属于某个环境,在某一个环境中变量不可重复定义;在环境与环境之间可以定义重复的变量;一个环境可以包含多个环境变量;常见环境分类:开发环境、测试环境、生产环境【一个项目生产部署上线】
15.2设置变量
全局变量:
环境变量:
15.3获取变量【请求参数是从params、headers、url中拿出来的,只要从界面中获取的[相当于从两个请求的postman界面中获取的];请求参数只能用在请求参数中,不可以用在代码区域{tests、请求前置脚本},可用在params、headers、bodys中】
全局变量:
环境变量:
【获取都用要一个变量去接收,多级的要一级一级取】
16.1地位:在send按钮点击后,请求前置脚本代码,第一时间被执行。在postman内部实际http请求之前。
16.2时间戳
概念:对应绝对时间----从1970年1月1日00:00:00到现在所经历的秒数
16.3案例
调用百度首页接口,传时间戳给服务器
实现步骤:
①拿到时间戳写入全局变量
//拿到时间戳数据值
var timestamp = new Date().getTime()
//将时间戳设置到全局变量中
pm.globals.set("glb_timestamp",timestamp)
②点击send按钮,发送请求。请求发送前执行上述代码,写入全局变量
③查看写入的变量:点击眼睛图标
④在请求参数(界面)中,使用全局变量。{{var_name}}【params是查询参数】
⑤在postman控制台,查看发送的http请求
【send发送请求之前会执行请求前置脚本,写进全局变量当中,再发送请求】
17.1介绍:应用于多个http请求之间,有数据关联、或依赖关系时。
17.2实现步骤
A接口依赖B接口的数据
①向B接口发送http请求,获取数据
②将数据保存至全局变量(环境变量)中
③A接口获取全局变量(环境变量)中数据值,进行使用
17.3案例
请求获取天气接口,提取响应结果中的城市,将城市名,给百度搜索接口使用
①发送天气接口请求,在天气接口的Tests中获取城市名,再把城市名写入
//获取全部响应结果
var jsondate=pm.response.json()
//从响应结果中,获取城市名
var city=jsondate.一级一级往下引用k名
//将城市名写入到全局变量
pm.globals.set(“city”,city)
【点击send按钮,发送请求,查看设置的全局变量。点击小眼睛,看全局变量名和全局变量值】
//修改百度搜索请求,使用全局变量,按城市名进行搜索
18.1批量执行用例集
Data:引入外部文件
18.2生成测试报告(newman)【在dos界面】
1.先把用例集执行,run
2.导出用例集
3.生成测试报告
①{ newman run 测试脚本文件【导出的json文件】}[可单独执行] -e 环境变量文件【没有环境变量就省略】 -d 测试数据文件 -r html【必写】 --reporter-html-export report.html【报告名称,report名可以修改】
【比如:登录接口,测一个用户,请求体的数据是写死的,要是测1000个用户,需要用到参数化】
【当http请求,使用的数据有较高相似度时,相同的请求时,考虑使用参数化(将数据组织到数据文件中)】
19.1数据文件简介
CSV:
优点:数据组织形式简单,适用于大量数据的场合
缺点:不支持bool类型数据(数据被postman读入后,自动添加“”包裹bool值);不支持多参、少参、无参、错误参数的接口测试;不支持复杂数据类型(如嵌套字典、列表)
【数值直接拿去用,非数值都加上“”】
JSON:
优点:支持bool类型;支持多参、少参、无参、错误参数的接口测试;支持复杂数据类型(如嵌套字典、列表)
缺点:对于相同的数据量,JSON数据文件大小要远大于CSV文件
19.2导入外部数据文件
CSV:【一定要utf8编码】
①创建XXX.CSV数据文件
②将数据写入到CSV文件中:第一行写入的是数据对应的字段名;从第二行向后依次是对应的数值,数据间用英文,分隔
③在Postman中,选中使用数据文件的用例集,导入数据文件【run->data:select file->选择导入文件->通过preview预览按钮,校验数据文件是否正确】
JSON:【可在json.cn网站里编写,编写好复制粘贴到记事本打开的json文件中】
①创建XXX.JSON数据文件
②在数据文件中,按json语法写入json数据。Postman要求,json格式的数据文件,数据内容的最外层,必须是[ ]。内部所有的数据用{ }存储
③在Postman中,选中使用数据文件的用例集,导入数据文件【run->data:select file->选择导入文件->通过preview预览按钮,校验数据文件是否正确】
【建议书写json数据时,无论是不是字符串,都可以用” ”包裹value值】
19.3读取数据文件数据
1.方法
①请求参数(请求行、请求头、请求体)中,使用数据文件中的数据
使用{{}}包裹csv文件字段名或json文件中的key
②代码(断言、请求前置脚本)中,使用数据文件中的数据
需要借助postman提供的关键字data点【.】csv文件字段名或json文件中的key
【send不能读外部数据文件,用到外部数据文件了,读取要进入到run里,通过run参数化用例集的按钮批量执行。如果有异常,借助控制台。】
小结:借助数据文件,实现“数据驱动”。有多少条数据,对应就有多少个http请求。
19.4生成测试报告
步骤:
①批量执行测试用例(借助数据文件)
②导出测试用例集(建议与数据文件放在一起)
③执行生成测试报告的命令
Newman run 用例集名称.json -d 数据文件名.csv/.json -r html --reporter-html-export 报告名称.html
拿到一个项目,要对项目整体有个认识:熟悉项目的功能;了解项目组织架构和相应技术。
20.1功能模块:XXXXXX【模块功能列出】
20.2技术栈
前端:页面显示........
后端:spring全家桶;mysql【实现数据持久化存储,断电也不会丢】+redis【缓存存储数据,读取快】+rabbitmq【消息队列,完成数据通信】
20.3技术架构图(比较详细展开描述技术栈)
20.4初始化项目环境(利用postman)
①先创建环境,给环境取名【测试、开发、生成】
②initial value:在外部数据文件中使用,current value:在postman中使用
【注意】:设置了环境,在执行用例的时候要选择对应环境
20.5数据依赖
1.登录成功,返回的“令牌”,被增删改查功能接口依赖
2.添加完的数据id,会被查、改、删依赖
【借助关联和环境变量实现】
20.6提取令牌
1.登录完成,返回data,不是完整令牌,缺少前缀
2.实现:
①发送http登录请求,在响应体中得到data值
var json_data = pm.response.json()
var env = json_data.data.token
②将data值拼接“Bearer”和“空格”,组成一个合法令牌
pm.environment.set("env","Bearer"+" "+env)
③将令牌写入环境变量中。(在Tests中通过代码写入)
20.7生成测试报告
1.在environment中有环境,要先导出环境
2.将环境文件与测试用例集放置到同一目录下
3.执行命令
663
*请认真填写需求信息,我们会在24小时内与您取得联系。