一、Python+unittest+requests+HTMLTestRunner 完整的接口自动化测试框架搭建_00——框架结构简解

首先配置好开发环境,下载安装Python并下载安装pycharm,在pycharm中创建项目功能目录。如果不会的可以百度Google一下,该内容网上的讲解还是比较多比较全的!

[图片上传中...(image-85e0c5-1598517112342-20)]

大家可以先简单了解下该项目的目录结构介绍,后面会针对每个文件有详细注解和代码。

common:

——configDb.py:这个文件主要编写数据库连接池的相关内容,本项目暂未考虑使用数据库来存储读取数据,此文件可忽略,或者不创建。本人是留着以后如果有相关操作时,方便使用。

——configEmail.py:这个文件主要是配置发送邮件的主题、正文等,将测试报告发送并抄送到相关人邮箱的逻辑。

——configHttp.py:这个文件主要来通过get、post、put、delete等方法来进行http请求,并拿到请求响应。

——HTMLTestRunner.py:主要是生成测试报告相关

——Log.py:调用该类的方法,用来打印生成日志

result:

——logs:生成的日志文件

——report.html:生成的测试报告

testCase:

——test01case.py:读取userCase.xlsx中的用例,使用unittest来进行断言校验

testFile/case:

——userCase.xlsx:对下面test_api.py接口服务里的接口,设计了三条简单的测试用例,如参数为null,参数不正确等

caselist.txt:配置将要执行testCase目录下的哪些用例文件,前加#代表不进行执行。当项目过于庞大,用例足够多的时候,我们可以通过这个开关,来确定本次执行哪些接口的哪些用例。

config.ini:数据库、邮箱、接口等的配置项,用于方便的调用读取。

getpathInfo.py:获取项目绝对路径

geturlParams.py:获取接口的URL、参数、method等

readConfig.py:读取配置文件的方法,并返回文件中内容

readExcel.py:读取Excel的方法

runAll.py:开始执行接口自动化,项目工程部署完毕后直接运行该文件即可

test_api.py:自己写的提供本地测试的接口服务

test_sql.py:测试数据库连接池的文件,本次项目未用到数据库,可以忽略

二、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_01——测试接口服务

首先,我们想搭建一个接口自动化测试框架,前提我们必须要有一个可支持测试的接口服务。有人可能会说,现在我们的环境不管测试环境,还是生产环境有现成的接口。但是,一般工作环境中的接口,不太满足我们框架的各种条件。举例如,接口a可能是get接口b可能又是post,等等等等。因此我决定自己写一个简单的接口!用于我们这个框架的测试!

按第一讲的目录创建好文件,打开test_api.py,写入如下代码

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="Python" cid="n89" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import flaskimport jsonfrom flask import request '''flask: web框架,通过flask提供的装饰器@server.route()将普通函数转换为服'''# 创建一个服务,把当前这个python文件当做一个服务server = flask.Flask(__name__)# @server.route()可以将普通函数转变为服务 登录接口的路径、请求方式@server.route('/login', methods=['get', 'post'])def login():    # 获取通过url请求传参的数据    username = request.values.get('name')    # 获取url请求传的密码,明文    pwd = request.values.get('pwd')    # 判断用户名、密码都不为空    if username and pwd:        if username == 'xiaoming' and pwd == '111':            resu = {'code': 200, 'message': '登录成功'}            return json.dumps(resu, ensure_ascii=False)  # 将字典转换字符串        else:            resu = {'code': -1, 'message': '账号密码错误'}            return json.dumps(resu, ensure_ascii=False)    else:        resu = {'code': 10001, 'message': '参数不能为空!'}        return json.dumps(resu, ensure_ascii=False) if __name__ == '__main__':    server.run(debug=True, port=8888, host='127.0.0.1') </pre>

执行test_api.py,在浏览器中输入http://127.0.0.1:8888/login?name=xiaoming&pwd=11199回车,验证我们的接口服务是否正常~

变更我们的参数,查看不同的响应结果确认接口服务一切正常

[图片上传中...(image-183dd6-1598517112341-18)]

三、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_02——配置文件读取

在我们第二讲中,我们已经通过flask这个web框架创建好了我们用于测试的接口服务,因此我们可以把这个接口抽出来一些参数放到配置文件,然后通过一个读取配置文件的方法,方便后续的使用。同样还有邮件的相关配置~

按第一讲的目录创建好config.ini文件,打开该文件写入如下:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="Python" cid="n98" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"># -*- coding: utf-8 -*-[HTTP]scheme = httpbaseurl = 127.0.0.1port = 8888timeout = 10.0   [EMAIL]on_off = on;subject = 接口自动化测试报告app = Outlookaddressee = songxiaobao@qq.comcc = zhaobenshan@qq.com</pre>

在HTTP中,协议http,baseURL,端口,超时时间。

在邮件中on_off是设置的一个开关,=on打开,发送邮件,=其他不发送邮件。subject邮件主题,addressee收件人,cc抄送人。

在我们编写readConfig.py文件前,我们先写一个获取项目某路径下某文件绝对路径的一个方法。按第一讲的目录结构创建好getpathInfo.py,打开该文件

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="Python" cid="n102" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import os def get_Path():    path = os.path.split(os.path.realpath(__file__))[0]    return path if __name__ == '__main__':# 执行该文件,测试下是否OK    print('测试路径是否OK,路径为:', get_Path())</pre>```填写如上代码并执行后,查看输出结果,打印出了该项目的绝对路径:![image](https://upload-images.jianshu.io/upload_images/24470939-ca8c9b26bc1ee8c6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240) 继续往下走,同理,按第一讲目录创建好readConfig.py文件,打开该文件,以后的章节不在累赘
```<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="Python" cid="n106" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import osimport configparserimport getpathInfo#引入我们自己的写的获取路径的类 path = getpathInfo.get_Path()#调用实例化,还记得这个类返回的路径为C:\Users\songlihui\PycharmProjects\dkxinterfaceTestconfig_path = os.path.join(path, 'config.ini')#这句话是在path路径下再加一级,最后变成C:\Users\songlihui\PycharmProjects\dkxinterfaceTest\config.iniconfig = configparser.ConfigParser()#调用外部的读取配置文件的方法config.read(config_path, encoding='utf-8') class ReadConfig():     def get_http(self, name):        value = config.get('HTTP', name)        return value    def get_email(self, name):        value = config.get('EMAIL', name)        return value    def get_mysql(self, name):#写好,留以后备用。但是因为我们没有对数据库的操作,所以这个可以屏蔽掉        value = config.get('DATABASE', name)        return value  if __name__ == '__main__':#测试一下,我们读取配置文件的方法是否可用    print('HTTP中的baseurl值为:', ReadConfig().get_http('baseurl'))    print('EMAIL中的开关on_off值为:', ReadConfig().get_email('on_off'))</pre>

执行下readConfig.py,查看数据是否正确

一切OK

四、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_03——读取Excel中的case

配置文件写好了,接口我们也有了,然后我们来根据我们的接口设计我们简单的几条用例。首先在前两讲中我们写了一个我们测试的接口服务,针对这个接口服务存在三种情况的校验。正确的用户名和密码,账号密码错误和账号密码为空

我们根据上面的三种情况,将对这个接口的用例写在一个对应的单独文件中testFile\case\userCase.xlsx ,userCase.xlsx内容如下:

紧接着,我们有了用例设计的Excel了,我们要对这个Excel进行数据的读取操作,继续往下,我们创建readExcel.py文件

结果为:

完全正确~

五、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_04——requests请求

配置文件有了,读取配置文件有了,用例有了,读取用例有了,我们的接口服务有了,我们是不是该写对某个接口进行http请求了,这时候我们需要使用pip install requests来安装第三方库,在common下configHttp.py,configHttp.py的内容如下:

执行该文件,验证结果正确性:

我们发现和浏览器中进行请求该接口,得到的结果一致,说明没有问题,一切OK

六、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_05——参数动态化

在上一讲中,我们写了针对我们的接口服务,设计的三种测试用例,使用写死的参数(result = RunMain().run_main('post', 'http://127.0.0.1:8888/login', 'name=xiaoming&pwd='))来进行requests请求。本讲中我们写一个类,来用于分别获取这些参数,来第一讲的目录创建geturlParams.py,geturlParams.py文件中的内容如下:

通过将配置文件中的进行拼接,拼接后的结果:http://127.0.0.1:8888/login?和我们请求的一致

七、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_06——unittest断言

以上的我们都准备好了,剩下的该写我们的unittest断言测试case了,在testCase下创建test01case.py文件,文件中内容如下:

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="Python" cid="n135" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import jsonimport unittestfrom common.configHttp import RunMainimport paramunittestimport geturlParamsimport urllib.parse# import pythoncomimport readExcel# pythoncom.CoInitialize() url = geturlParams.geturlParams().get_Url()# 调用我们的geturlParams获取我们拼接的URLlogin_xls = readExcel.readExcel().get_xls('userCase.xlsx', 'login') @paramunittest.parametrized(*login_xls)class testUserLogin(unittest.TestCase): def setParameters(self, case_name, path, query, method): """ set params :param case_name: :param path :param query :param method :return: """ self.case_name = str(case_name) self.path = str(path) self.query = str(query) self.method = str(method) def description(self): """ test report description :return: """ self.case_name def setUp(self): """ :return: """ print(self.case_name+"测试开始前准备") def test01case(self): self.checkResult() def tearDown(self): print("测试结束,输出log完结\n\n") def checkResult(self):# 断言 """ check test result :return: """ url1 = "http://www.xxx.com/login?" new_url = url1 + self.query data1 = dict(urllib.parse.parse_qsl(urllib.parse.urlsplit(new_url).query))# 将一个完整的URL中的name=&pwd=转换为{'name':'xxx','pwd':'bbb'} info = RunMain().run_main(self.method, url, data1)# 根据Excel中的method调用run_main来进行requests请求,并拿到响应 ss = json.loads(info)# 将响应转换为字典格式 if self.case_name == 'login':# 如果case_name是login,说明合法,返回的code应该为200 self.assertEqual(ss['code'], 200) if self.case_name == 'login_error':# 同上 self.assertEqual(ss['code'], -1) if self.case_name == 'login_null':# 同上 self.assertEqual(ss['code'], 10001)</pre>

八、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_07——HTMLTestRunner

按我的目录结构,在common下创建HTMLTestRunner.py文件,内容如下:

九、Python+unittest+requests+HTMLTestRunner完整的接口自动化测试框架搭建_08——调用生成测试报告

先别急着创建runAll.py文件(所有工作做完,最后我们运行runAll.py文件来执行接口自动化的测试工作并生成测试报告发送报告到相关人邮箱),但是我们在创建此文件前,还缺少点东东。按我的目录结构创建caselist.txt文件,内容如下个文件的作用是,我们通过这个文件来控制,执行哪些模块下的哪些unittest用例文件。如在实际的项目中:user模块下的test01case.py,店铺shop模块下的我的店铺my_shop,如果本轮无需执行哪些模块的用例的话,就在前面添加#。我们继续往下走,还缺少一个发送邮件的文件。在common下创建configEmail.py文件,内容如下:

运行configEmail.py验证邮件发送是否正确

邮件已发送成功,我们进入到邮箱中进行查看,一切OK~~不过这我要说明一下,我写的send_email是调用的outlook,如果您的电脑本地是使用的其他邮件服务器的话,这块的代码需要修改为您想使用的邮箱调用代码

如果遇到发送的多个收件人,但是只有第一个收件人可以收到邮件,或者收件人为空可以参考http://www.361way.com/smtplib-multiple-addresses/5503.html

继续往下走,这下我们该创建我们的runAll.py文件了

执行runAll.py,进到邮箱中查看发送的测试结果报告,打开查看

然后继续,我们框架到这里就算基本搭建好了,但是缺少日志的输出,在一些关键的参数调用的地方我们来输出一些日志。从而更方便的来维护和查找问题。

按目录结构继续在common下创建Log.py,内容如下:

<pre spellcheck="false" class="md-fences mock-cm md-end-block" lang="Python" cid="n155" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: pre-wrap; background-image: inherit; background-position: inherit; background-size: inherit; background-repeat: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-radius: 3px; padding: 8px 4px 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; color: rgb(51, 51, 51); font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">import osimport loggingfrom logging.handlers import TimedRotatingFileHandlerimport getpathInfo path = getpathInfo.get_Path()log_path = os.path.join(path, 'result')  # 存放log文件的路径  class Logger(object):    def __init__(self, logger_name='logs…'):        self.logger = logging.getLogger(logger_name)        logging.root.setLevel(logging.NOTSET)        self.log_file_name = 'logs'  # 日志文件的名称        self.backup_count = 5  # 最多存放日志的数量        # 日志输出级别        self.console_output_level = 'WARNING'        self.file_output_level = 'DEBUG'        # 日志输出格式        self.formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')     def get_logger(self):        """在logger中添加日志句柄并返回,如果logger已有句柄,则直接返回"""        if not self.logger.handlers:  # 避免重复日志            console_handler = logging.StreamHandler()            console_handler.setFormatter(self.formatter)            console_handler.setLevel(self.console_output_level)            self.logger.addHandler(console_handler)             # 每天重新创建一个日志文件,最多保留backup_count份            file_handler = TimedRotatingFileHandler(filename=os.path.join(log_path, self.log_file_name), when='D',                                                    interval=1, backupCount=self.backup_count, delay=True,                                                    encoding='utf-8')            file_handler.setFormatter(self.formatter)            file_handler.setLevel(self.file_output_level)            self.logger.addHandler(file_handler)        return self.logger  logger = Logger().get_logger()</pre>

然后我们在需要我们输出日志的地方添加日志:

我们修改runAll.py文件,在顶部增加import common.Log,然后增加标红框的代码

让我们再来运行一下runAll.py文件,发现在result下多了一个logs文件,我们打开看一下有没有我们打印的日志

OK,至此我们的接口自动化测试的框架就搭建完了,后续我们可以将此框架进行进一步优化改造,使用我们真实项目的接口,结合持续集成定时任务等,让这个项目每天定时的来跑啦~~~

在学习的这段时间,整理资料已经成了我的习惯!下面是我对上面三个阶段学习的收集和整理
对于学习软件测试的的朋友来说应该是最全面的备战仓库了,有很多朋友靠着这些内容进行复习,拿到了BATJ等大厂的offer,这个仓库也已经帮助了很多的软件测试的学习者,希望也能帮助到你!

乾坤未定,你我皆是黑马

关注微信公众号:【程序员二黑】 即可免费获取这份仓库资源啦!

Python+unittest+requests 接口自动化测试框架搭建 完整的框架搭建过程 实战相关推荐

  1. python接口自动化测试框架unittest代码_Python+unittest+requests 接口自动化测试框架搭建教程...

    | | | | HEADING | | +----------------+ | | | | | | +----------------+ | | | | REPORT | | +---------- ...

  2. pythonunittest接口测试_基于python+unittest +requests接口测试

    2019独角兽企业重金招聘Python工程师标准>>> 谈到接口测试,大家都不会感到陌生.接口测试的工具和实现方式也有很多,比如ant+jmeter+jemkins.postman. ...

  3. 【python+pytest】接口自动化测试—接口基础篇

    目录 前言 接口定义 接口分类 常见接口 测试分层 测试左移和右移 写在最后,给与的建议: 前言 就当前软件测试招聘的市场需求以及趋势而言,接口测试是测试人员必须掌握的技能,而接口自动化测试则是加薪利 ...

  4. python+unittest+requests+HTMLTestRunner 框架通过读取excel测试用例实现接口自动化测试

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.接口自动化框架目录 二.读取相应配置文件testFile目录 1.创建配置文件 2.获取当前目录代码getpathinf ...

  5. python+requests接口自动化测试框架实例详解教程(米兔888)

    来源:https://my.oschina.net/u/3041656/blog/820023 源码:https://pan.baidu.com/s/1lgIEToiczTvvjy--p-N20g 提 ...

  6. python+requests接口自动化测试框架实例详解教程(米兔888)【适合半年或一年以上天天做自动化经验的大神下载使用】

    来源:https://my.oschina.net/u/3041656/blog/820023 源码地址,需要的回复评论留下邮箱 前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测 ...

  7. python+requests接口自动化测试框架实例详解教程

    前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接口的自 ...

  8. 全网独一份python+requests接口自动化测试框架实例详解教程

    前言 前段时间由于公司测试方向的转型,由原来的web页面功能测试转变成接口测试,之前大多都是手工进行,利用postman和jmeter进行的接口测试,后来,组内有人讲原先web自动化的测试框架移驾成接 ...

  9. 软件测试必学之python+unittest+requests+HTMLRunner编写接口自动化测试集

    问题描述: 搭建接口测试框架,执行用例请求多个不同请求方式的接口 实现步骤: ① 创建配置文件config.ini,写入部分公用参数,如接口的基本url.测试报告文件路径.测试数据文件路径等配置项 1 ...

最新文章

  1. BCH社区意见分歧:引领市场VS迎合市场?
  2. 当网站遇到黑链时该如何进行处理?
  3. c与python的区别-c语言和python的区别是什么
  4. Linq Coding -- Part Three [Let子句]
  5. build.gradle代码
  6. MySQL配置mycat读写分离:wrapper | Startup failed: Timed out waiting for signal from JVM.
  7. 异常处理---SpringMVC学习笔记(十)
  8. apple组织名称是什么_什么是Apple Macintosh?
  9. 吴恩达深度学习之三《结构化机器学习项目》学习笔记
  10. Matlab实现熵权法并计算权重和综合评分——附增完整代码和测试用例
  11. java前后端分离,前端部署的方式
  12. OFDM转向FBMC
  13. stm32毕业设计 单片机车牌识别系统
  14. NumPy学习笔记21. IO
  15. 2019趋势科技面经
  16. 嵌入式开发板模拟器:QEMU
  17. Buy and Resell
  18. Tensorflow学习笔记——Summary用法
  19. 统计学总结之Bias(偏差),Error(误差),和Variance(方差)的区别
  20. win7正版版本分析

热门文章

  1. 如何屏蔽谷歌浏览器的账号密码自动填充和账号密码选择
  2. 拯救者R9000X显卡驱动安装
  3. ExtremeNet:Bottom-up Object Detection by Grouping Extreme and Center Points
  4. 2017web前端校招面试总结 - 陌陌技术保障组
  5. 【LittleVGL】stm32f412-discovery探索板-ft6x06驱动问题
  6. 车内贵重物品检测方案总结
  7. burp抓包mumu模拟器
  8. ArrayIndexOutOfBoundsException: 4096 while reading gif file
  9. U-Boot参数设置
  10. 《Fundamentals Of Computer Graphics》虎书第三版翻译——第五章 线性代数