1.djangoå¦ä½å®è£
mysqlï¼
2.MySQLdb属性和方法
3.ADODB.Recordset (0x800A0BCD)BOF 或 EOF 中有一个是“真”,或者当前的记录已被删除
4.python接口自动化-python操作mysql数据库(详解)
djangoå¦ä½å®è£ mysqlï¼
导读ï¼ä»å¤©é¦å¸CTOç¬è®°æ¥ç»åä½åäº«å ³äºdjangoå¦ä½å®è£ mysqlçç¸å ³å 容ï¼å¦æè½ç¢°å·§è§£å³ä½ ç°å¨é¢ä¸´çé®é¢ï¼å«å¿äºå ³æ³¨æ¬ç«ï¼ç°å¨å¼å§å§ï¼å¦ä½å¨Django1.6ç»åPython3.4çæ¬ä¸ä½¿ç¨MySqlå ³äºDjango1.6ä¸DATABASESç设置ä¹æ¯ä¸æ ·ä¸ç¨åä»»ä½ä¿®æ¹ï¼è·ä»¥åMySQLdbçæ¶åä¸æ ·ï¼å¦ä¸æ示ï¼1DATABASES={ 2'default':{ 3'ENGINE':'django.db.backends.mysql',#æ°æ®åºå¼æ4'NAME':'test',#æ°æ®åºå5'USER':'root',#ç¨æ·å6'PASSWORD':'root',#å¯ç 7'HOST':'',#æ°æ®åºä¸»æºï¼é»è®¤ä¸ºlocalhost8'PORT':'',#æ°æ®åºç«¯å£ï¼MySQLé»è®¤ä¸º'OPTIONS':{ 'autocommit':True,},}}æå ³é®çä¸ç¹ï¼å¨ç«ç¹ç__init__.pyæ件ä¸ï¼æ·»å å¦ä¸ä»£ç ï¼1importpymysql2pymysql.install_as_MySQLdb()åå®ä¸è¿°å¨ä½åï¼å³å¯å¨djangoä¸è®¿é®mysqläºã
django1.æä¹å®è£ mysql
使ç¨MySQLå®æ¹çmysql.connector模å
å®è£ mysql.connector模å
#å»mysql.comå®ç½ä¸ä¸è½½å 并解å
#cdå°è§£åæ件çæ ¹ç®å½ï¼è¯¥ç®å½ä¸åºè¯¥æä¸ä¸ªsetup.pyçæ件ï¼
pythonsetup.pyinstall
djangoæä¹ä½¿ç¨æ¬æºmysqlæ°æ®åºstep1:
ä¿®æ¹ä½ çdjangoprojectç®å½ä¸çsettings.pyæ件è³å¦ä¸æ示ï¼
å ¶ä¸ï¼'NAME'对åºçâdb_name'æ¯ä½ äºå 使ç¨mysql
çå½ä»¤è¡æ示符å建çæ°æ®åºå称ã注æï¼å¨django使ç¨æ°æ®åºä¹åï¼ä½ å¿ é¡»å å建åºæ°æ®åºï¼å¦åä¼æ¥éã'USER'对åºç'username'
è¿æ'PASSWORD'对åºçâpasswd'
å°±æ¯ä½ å¨mysqlä¸å建çç¨æ·ååå¯ç ãå¦æä½ æå¤ä¸ªçè¯ï¼é便填ä¸ä¸ªå°±å¥½ã'HOST'å'PORT'é»è®¤é½å¯ä»¥ä¸å¡«ã
é¢å¤è¯ï¼ä½¿ç¨ç¨æ·ååå¯ç ç»å½mysqlçæ¹æ³ï¼
é¦å ï¼ä½ éè¦è¿å ¥mysql/binçç®å½ä¸ï¼ä¹å¯ä»¥å¨.bash_profileä¸è®¾ç½®ç¯å¢åéï¼
PATH=/usr/local/bin:/usr/bin:/bin:/sbin:/usr/sbin:/usr/local/sbin:/usr/local/Cellar/mysql/5.6./bin/
åå¨promptè¾å ¥mysql-uusername-p,å车ååè¾å ¥passwdå³å¯
step2:
ç¶åï¼å¨manage.pyè·¯å¾ä¸ä½¿ç¨pythonmanage.pysyncdbè¯è¯ï¼ç»æä¼æç¤ºä½ é误æ¾ä¸å°MySQLdbè¿ä¸ªmodule,为ä»ä¹å¢ï¼å 为pythonmanage.pysyncdbå½ä»¤æ¯è¿æ ·å·¥ä½çï¼
1.å¨projectç®å½çsettings.pyçINSTALLED_APPSå ç»ä¸æ¾å°å¯è½éè¦æ´æ°çAPPã
2.æ¾å°æ¯ä¸ä¸ªAPPç®å½ä¸çmodels.py(å ³ç³»å®ä¹æ件)ï¼å¹¶é对ååå¨æ°æ®åºä¸è¿è¡æ´æ°ã
说äºè¿ä¹å¤ï¼åé¢é£ä¸ªé误æ¾ä¸å°moduleMySQLdbæ¯ä»ä¹ææåï¼
å ç»ä¸ªå¾ï¼å解éï¼
å 为å¨models.pyä¸å®ä¹å ³ç³»ä½¿ç¨çæ¯pythonï¼èçæ£å¨æ°æ®åºä¸æä½å½¢æmodelå½ç¶ä¸å®è¦ç¨sqlè¯å¥ï¼æä»¥å¿ é¡»è¦æä¸äºåè½æ¨¡å
æ¥æpythonè¯å¥è½¬åæsqlè¯å¥ãå¦æä½ ä½¿ç¨sqliteçè¯ï¼ç±äºsqliteå转å模åé½å·²ç»ç±pythonå ç½®äºï¼æ以ç´æ¥ä½¿ç¨ä¸ä¼åçé
误ãä½æ¯âmysqlè¯å¥ç转å模åâå°±éè¦ä½ æå¨å è½½äºï¼è¿äºæ¨¡åæ¾å¨MySQL-pythonä¸ã
ææ¯ä½¿ç¨pipå®è£ çï¼
å®è£ äºä¹åï¼å使ç¨pythonmanage.pysyncdbå°±OKå¦ã
æ使ç¨çç³»ç»æ¯OSXï¼ä¸é¢æ¯mysqlé»è®¤çå®è£ è·¯å¾
/usr/local/Cellar/mysql/5.6./
å¦æä½ æ³ç¥éä½ çæ°æ®åºæ件æ¯æ¾å¨åªéçï¼ä½ å¯ä»¥æ¥çmysql_configæ件ä¸çldataåéï¼è¿ä¸ªåéçå¼å°±æ¯é»è®¤çæ°æ®åºæ件夹åå¨çè·¯å¾ãæçç³»ç»ä¸ï¼mysql_configçå®æ´è·¯å¾æ¯ï¼
/usr/local/Cellar/mysql/5.6./bin/mysql_config
å¦ä½å°djangoä¸çsqlite3æ¢æmysqldjango
æ°æ®åºä½¿ç¨ï¼sqlite3åmysqlï¼
ä¸ãsqlite3
使ç¨
1ãimport
sqlite3
确认系ç»ä¸æ¯å¦å®è£
2ãè¿å ¥å½å项ç®ç®å½ï¼cmdåè¿è¡pythonï¼è¿å ¥å½ä»¤è¡æ¨¡å¼
3ãimport
sqlite3,
sqlite3.connect('{ path\name.db}')
#大æ¬å·å 表示èªå®ä¹ï¼çå®æ åµæ²¡æ大æ¬å·
4ãä¿®æ¹settings.pyæ件
DATABASES
=
{
'default':
{
'ENGINE':
'django.db.backends.sqlite3',
'NAME':
{ path\name.db}',
'USER':
'',
'PASSWORD':
'',
'HOST':
'',
'PORT':
'',
}
}
5ãè¿å ¥æ°æ®åºæ件çé¢ï¼è¿è¡python
manage.py
shell
from
django.db
import
connection
cur
=
connection.cursor()
å¦æ没æ¥éï¼å表示é ç½®æå
6ãä¿®æ¹models.pyæ件ï¼é ç½®èªå·±ç表
ä¾å¦ï¼
from
django.db
import
models
from
django.contrib
import
admin
#
Create
your
models
here.
class
BlogPost(models.Model):
title
=
models.CharField(max_length
=
)
body
=
models.TextField()
timestamp
=
models.DateTimeField()
class
Meta:
ordering
=
['-timestamp']
7ãå建æ°æ®åºå 容
python
manage.py
syncdb
æ ¹æ®æ示è¾å ¥ï¼è¡¨ç¤ºè¿æ¥æå
注ï¼ä»¥ä¸åªè¡¨ç¤ºå¯¹æ°æ®åºçå建ï¼è¿æ¥å使ç¨ï¼ä¸å å«å ¶å®å 容ã
äºãmysql
1ã确认å®è£ mysqlæ°æ®åº
2ãå¨mysqlä¸å建æ°æ®åº
å½ä»¤æ¨¡å¼ä¸å¯ä»¥ä½¿ç¨
CREATE
DATABASE
{ name}
DEFAULT
CHARSET=utf8;
3ãä¿®æ¹settings.pyæ件
DATABASES
=
{
'default':
{
'ENGINE':
'django.db.backends.mysql',
'NAME':
'{ name}',
'USER':
'{ username}',
'PASSWORD':
'{ password}',
'HOST':'localhost',
#ip
'PORT':'',
}
}
4ãä¿®æ¹models.pyæ件ï¼é ç½®èªå·±ç表
ä¾å¦ï¼
from
django.db
import
models
from
django.contrib
import
admin
#
Create
your
models
here.
class
BlogPost(models.Model):
title
=
models.CharField(max_length
=
)
body
=
models.TextField()
timestamp
=
models.DateTimeField()
class
Meta:
ordering
=
['-timestamp']
5ãå建æ°æ®åºå 容
python
manage.py
syncdb
æ ¹æ®æ示è¾å ¥ï¼è¡¨ç¤ºè¿æ¥æå
å¦ä½å¨Django1.7ç»åPython3.4çæ¬ä¸ä½¿ç¨MySql1ï¼å®è£ python_to_mysqlå
2ï¼å¨settings.pyéé¢é ç½®MySQLè¿æ¥ï¼
ç¶åå°±å¯ä»¥ç¨äºï¼æ³æ´å¥½çå¦ä¹ pythonè¯·å ³æ³¨å¾®ä¿¡å ¬ä¼å·âPythonåºç¡æç¨âï¼
macosx.7æä¹æ建djangomysqlç¯å¢æä½ç³»ç»ï¼LinuxCentOS5/MaxOSX.6snowleopard
ç¸å ³ç¯å¢ï¼Python2.6.4;MySQL5.1.
å®è£ çæ¬ï¼MySQL-python-1.2.3c1
æ¹æ³/æ¥éª¤
é¦å è¦ä¸è½½ä¸è½½ï¼è¯·å°å®æ¹ç½ç«
解åï¼tarzxvfMySQL-python
*è¿å ¥æ件ç®å½ï¼è¿è¡ä»¥ä¸å½ä»¤ï¼sudopythonsetup.pyinstall
å®è£ å®æï¼å°ä½ çpythonå®è£ ç®å½ä¸çsite-packagesç®å½éæ£æ¥ä»¥ä¸æ件æ¯å¦åå¨ï¼å¦æåå¨å³ä»£è¡¨å®è£ æåäºLinuxï¼MySQL_python-1.2.3c1-py2.6-linux-i.eggMacOSXï¼MySQL_python-1.2.3c1-py2.6-macosx-.4-x_.egg注ï¼å¦æ碰å°mysql_confignotfoundçé®é¢ï¼æ两ç§æ¹æ³è§£å³ï¼1ï¼sudoln-s/usr/local/mysql/bin/mysql_config/usr/local/bin/mysql_configå°mysql_confiä»ä½ çå®è£ ç®å½é¾æ¥å°/usr/local/binç®å½ä¸ï¼è¿æ ·å°±å¯ä»¥å¨ä»»æç®å½ä¸è®¿é®äºï¼ä¹å¯ä»¥æ¾å°/usr/binï¼2ï¼ç¼è¾æºç æ件夹çsite.cfgæ件ï¼å»æ#mysql_config=/usr/local/bin/mysql_configåç注éï¼ï¼ä¿®æ¹åé¢çè·¯å¾ä¸ºä½ çmysql_configçæ£çç®å½å°±å¯ä»¥äºãï¼å¦æä¸ç¥émysql_configå¨åªéï¼è¿è¡å½ä»¤ï¼whereismysql_configï¼
æµè¯æ¹æ³1ï¼è¿è¡å½ä»¤pythonè¿å ¥pythonè¿è¡ç¯å¢2ï¼è¾å ¥ä»¥ä¸python代ç è¿è¡æµè¯importMySQLdbtest=MySQLdb.connect(db='mydb',host='myhost',user='u',passwd='p')cur=test.cursor()cur.execute('showdatabases;')fordataincur.fetchall():printdata3ï¼å¦æä½ å¨å±å¹ä¸çå°äºä½ å 个æ°æ®åºçåºåçè¾åºä»£è¡¨ä½ å®è£ æåäº
å¯è½ç¢°å°çé®é¢1ï¼é®é¢ï¼ImportError:libmysqlclient_r.so.:cannotopensharedobjectfile:Nosuchfileordirectoryåå æ¯pythonæ æ³æ¾å°mysqlç®å½ä¸çlibmysqlclient_r.so.å¨æåº,å ¶å®MySQLdbæ¯è°ç¨mysqlçcå½æ°åº.æ以æ¬æºä¸é¦å å¾å®è£ äºmysqlç¶å:exportLD_LIBRARY_PATH=/usr/local/mysql/lib/mysql:$LD_LIBRARY_PATH并ä¸å°/usr/local/mysql5.1/lib/mysqlæ¾å ¥/etc/ld.so.confä¸/etc/ld.so.confæ¹åå 容为ï¼includeld.so.conf.d/*.conf/usr/local/mysql5.1/lib/mysql
7
ldconfigæåéæ°åæµè¯ä¸ä¸ï¼å°±ä¸ä¼æä¸é¢çé®é¢äº
ç»è¯ï¼ä»¥ä¸å°±æ¯é¦å¸CTOç¬è®°ä¸ºå¤§å®¶æ´ççå ³äºdjangoå¦ä½å®è£ mysqlçç¸å ³å 容解çæ±æ»äºï¼å¸æ对æ¨ææ帮å©ï¼å¦æ解å³äºæ¨çé®é¢æ¬¢è¿å享ç»æ´å¤å ³æ³¨æ¤é®é¢çæååï½
MySQLdb属性和方法
MySQLdb属性和方法概述如下: DATABINARY是一个预定义的DBAPISet,包含了整数至。DATE包含和。NULL值被定义为'NULL'。NUMBER包含0到的im即时通讯源码下载免费整数,表示不同的数据类型。ROWID为空列表,可能表示无关联的主键。STRING包括、和。TIME对应的DBAPISet值为。TIMESTAMP的DBAPISet包括和7。 __all__列表包含了模块中的多个类和函数,如Binary、Connect、Connection等。此外,还有模块的作者信息,修订版本和警告注册表等元数据。 apilevel属性设置为'2.0',表示支持的社交分享php源码API级别。paramstyle是'format',描述了参数的格式。threadsafety为1,表示多线程环境下的安全等级。version_info是一个元组,记录了模块的版本信息。 模块提供了几个核心函数,如Binary()用于操作二进制数据,Connect()是连接数据库的工厂函数,以及DateFromTicks()、TimeFromTicks()和TimestampFromTicks()用于转换时间戳。connect()同样为连接数据库提供接口。 还有一些调试相关的函数,如debug(),但需注意它需要支持调试的编译客户端库。escape()和其变体用于特殊字符转义,如escape_string()用于字符串转义,而escape_dict()和escape_sequence()则适用于字典和序列的转义。 get_client_info()函数返回表示客户端库版本的字符串,而string_literal()则将对象转换为SQL字符串,确保特殊字符被正确转义并用单引号包围。hdmi源码与解码扩展资料
MySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQLAB公司。在年1月号被Sun公司收购。目前MySQL被广泛地应用在Internet上的中小型网站中。由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,许多中小型网站为了降低网站总体拥有成本而选择了MySQL作为网站数据库。ADODB.Recordset (0xA0BCD)BOF 或 EOF 中有一个是“真”,或者当前的记录已被删除
<html>
<head>
<title>演示对象Recordset的使用</title>
</head>
<body>
<%
'Server对象的CreateObject方法建立Connection对象
Set Conn=Server.CreateObject("ADODB.Connection")
'设置Connection对象的ConnectionString
'Driver表示ODBC驱动程序
'Server表示数据库服务器名称
Conn.ConnectionString="Provider=SQLNCLI.1;Password=sa;Persist Security Info=True;User ID=sa;Initial Catalog=MYSQLDB;Data Source=localhost"
Conn.Open
'定义Recordset对象
Set rs=Server.CreateObject("ADODB.RecordSet")
'设置rs的ActiveConnection的属性,绑定到连接
Set rs.ActiveConnection = Conn
'设置游标类型
rs.cursortype = 3
'打开记录集
rs.Open"SELECT * FROM Departments"',Conn,1,3
'显示记录集中记录数量
Response.Write("表Departments中包含"&CStr(rs.RecordCount)&"条记录<br>")
'移动指针到记录集的最后
rs.Move rs.RecordCount
'判断rs.EOF属性
if rs.EOF=true then
Response.write("已经到达记录集的结尾,Move方法和EOF属性检测正常")
End if
'断开与数据库的连接
Conn.Close
'释放Connection对象,关闭数据库
Set Conn=nothing
%>
</body>
</html>
python接口自动化-python操作mysql数据库(详解)
现在的招聘要求对QA人员的要求越来越高,测试的一些基础知识就不必说了,来说测试知识以外的,会不会一门或者多门开发与语言,能不能读懂代码,会不会Linux,会不会搭建测试系统,会不会常用的gomodule智能源码数据库,会不会SQL等等。因此,这篇文章来讲解如何使用Python语言操作MySQL数据库。
本科阶段曾学过使用java对MySQL数据库进行操作,基本思路是先连接数据库,然后执行SQL语句对数据库进行操作,最后打印结果并断开连接。使用Python操作数据库的流程和以上过程基本一致,在对其进行介绍之前,先介绍一些基本的概念。
以流程图的方式展示Python操作MySQL数据库的流程:首先创建Connection对象(数据库连接对象),用于打开数据库连接;然后创建Cursor对象(游标对象)用于执行查询和获取结果;接着执行SQL语句对数据库进行增删改查等操作并提交事务,此过程如果出现异常则使用回滚技术使数据库恢复到执行SQL语句之前的状态;最后,销毁Cursor对象和Connection对象,以避免多计算机内存过多的占用和浪费。
下面依次对Connection对象、Cursor对象和事务等概念进行介绍。
Connection对象即为数据库连接对象,在Python中可以使用`py mysql.connect()`方法创建Connection对象,该方法的常用参数如下:host(连接的数据库服务器主机名,默认为本地主机);user(用户名,雪花算法的源码默认为当前用户);passwd(密码,无默认值);db(数据库名称,无默认值);port(指定数据库服务器的连接端口,默认为);charset(连接字符集)。
Connection对象常用的方法如下:cursor()(使用当前连接创建并返回游标)、commit()(提交当前事务)、rollback()(回滚当前事务)、close()(关闭当前连接)。
Cursor对象即为游标对象,用于执行查询和获取结果,在Python中可以使用`conn.cursor()`创建,其中`conn`为Connection对象。Cursor对象常用的方法和属性如下:execute()(执行数据库查询或命令,将结果从数据库获取到客户端)、fetchone()(获取结果集的下一行)、fetchmany()(获取结果集的下几行)、fetchall()(获取结果集中剩下的所有行)、close()(关闭当前游标对象)、rowcount(最近一次的execute返回数据的行数或受影响的行数)。
事务是数据库理论中一个比较重要的概念,指访问和更新数据库的一个程序执行单元,具有ACID特性:原子性、一致性、隔离性、持久性。在开发时,我们以以下三种方式使用事务:正常结束事务(`conn.commit()`)、异常结束事务(`conn.rollback()`)、关闭自动commit(设置`conn.autocommit(False)`)。
使用Python实现对MySQL数据库的增删改查等操作。在Python中操作MySQL数据库时,要使用的模块是:Python2中`mysqldb`(`pip2 install mysqldb`),Python3中`pymysql`(`pip3 install pymysql`)。本篇博客所使用的环境为:Python 3.7、win 、PyCharm .3.5、pymysql 0.9.2、MySQL 5.6。
下面将以具体代码的形式依次介绍Python中如何实现对MySQL数据库的增删改查等操作。
Python 标准数据库接口为Python DB-API,Python DB-API为开发人员提供了数据库应用编程接口。
Python 数据库接口支持非常多的数据库,你可以选择适合你项目的数据库:你可以访问Python数据库接口及API查看详细的支持数据库列表。
不同的数据库你需要下载不同的DB API模块,例如你需要访问Oracle数据库和Mysql数据,你需要下载Oracle和MySQL数据库模块。
DB-API 是一个规范,它定义了一系列必须的对象和数据库存取方式,以便为各种各样的底层数据库系统和多种多样的数据库接口程序提供一致的访问接口。
Python的DB-API,为大多数的数据库实现了接口,使用它连接各数据库后,就可以用相同的方式操作各数据库。
Python DB-API使用流程:什么是MySQLdb? PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb。
PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库。
如何安装MySQLdb? 在使用 PyMySQL 之前,我们需要确保 PyMySQL 已安装。PyMySQL 下载地址:github.com/PyMySQL/PyMy...
数据库连接前,请先确认以下事项:查看有没有创建数据库TESTDB(测试数据库),打开MySQL的client界面输入密码后,输入命令:查看没有那个数据库,那我们就开始创建一个TESTDB数据库,输入命令:再次输入第一步的命令查看,看到已经成功创建。查看TESTDB数据库里,有没有EMPLOYEE(测试用的测试表),输入命令:查看到在TESTDB数据库中没有EMPLOYEE表,那么没有我们就创建一张EMPLOYEE表即可。
创建一个实例,运行结果:(从结果中我们可以看见成功创建了一个Connection和Cursor对象。)下面将以具体代码的形式依次介绍Python中如何实现对MySQL数据库的增删改查等操作。
实例:1、连接数据库运行结果:参考代码:2、创建数据库表如果数据库连接存在我们可以使用execute()方法来为数据库创建表,如下所示创建表EMPLOYEE:运行代码后查看有没有表创建,输入命令:运行结果:参考代码:3、数据库插入操作以下实例使用执行 SQL INSERT 语句向表 EMPLOYEE 插入记录:1、首先查询有没有记录输入查询语句:代码实现:运行结果:再次查看有没有记录,输入第一步的sql语句:(可以看到插入一条记录)参考代码:另一种写法:实例:以下代码使用变量向SQL语句中传递参数:3、数据库查询操作Python查询Mysql使用 fetchone() 方法获取单条数据, 使用fetchall() 方法获取多条数据。实例:查询EMPLOYEE表中salary(工资)字段大于的所有数据:运行结果:参考代码:4、数据库更新操作更新操作用于更新数据表的的数据,以下实例将 EMPLOYEE 表中的 SEX 字段为 'M' 的 AGE 字段递增 5:1、以前age是,代码实现:运行结果:4、查询age变更到了没有5、参考代码:5、删除操作删除操作用于删除数据表中的数据,以下实例演示了删除数据表 EMPLOYEE 中 AGE 大于 的所有数据:1、大于的只有一条,删除了就没有记录了,输入代码实现:运行结果:查看数据库表,重复第一步参考代码执行事务事务机制可以确保数据一致性。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。Python DB API 2.0 的事务提供了两个方法 commit 或 rollback。实例:对于支持事务的数据库,在Python数据库编程中,当游标建立之时,就自动开始了一个隐形的数据库事务。commit()方法游标的所有更新操作,rollback()方法回滚当前游标的所有操作。每一个方法都开始了一个新的事务。
错误处理DB API中定义了一些数据库操作的错误及异常,下表列出了这些错误和异常:最后在我的QQ技术交流群里整理了我这几年软件测试生涯整理的一些技术资料,包括:电子书,简历模块,各种工作模板,面试宝典,自学项目等。如果在学习或工作中遇到问题,群里也会有大神帮忙解答,群号 ( 备注 知乎 )
全套软件测试自动化测试教学视频G教程资料下载视频教程+PPT+项目源码全套软件测试自动化测试大厂面经