admin 管理员组文章数量: 893697
【JAVA】关于自动化测试所需要学习的java基础知识笔记
文章目录
- 1.JAVA相关
- 1.1 java三大特性
- 1.2 抽象类和接口的区别
- 1.3 反射
- 1.3.1 反射的思想
- 1.3.2 什么是反射
- 1.3.3 xml解析代码
- 1.3.4 通过字节码可以使用的方法
- 1.4 HashMap和HashSet
- 1.5 File类和IO类
- 1.6 log4j的使用
- 2. 正则表达式
- 3.XML
- 3.1 dom4j
- 3.2 dom4j解析技术
- 4. JDBC
- 4.1 什么是JDBC以及一些基础的SQL语句
- 4.1.1 创建表
- 4.1.2 插入行
- 4.1.3 删除行
- 4.1.4 更新数据
- 4.1.5 查询数据
- 4.1.6 连接
- 4.2 工具 Navicat Premium 的下载与破解
- 4.3 操作步骤
- 4.4 写一个简单的DBUtil框架
- 5.TestNG
- 5.1 单元测试的概念
- 5.2 TestNG的安装
- 5.3 项目集成testNG
- 5.4 testNG的书写和运行
- 5.5 eclipse 乱码问题
- 5.6 testNG中一些常用的注解
- 5.7 TestNG 执行 junit 测试
- 5.8 断言
- 5.9 数据驱动(Data Provider)
1.JAVA相关
1.1 java三大特性
封装,继承,多态。
其中多态详解请看这篇博文:
.html
当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
其中有一个经典实例:
1.2 抽象类和接口的区别
1.3 反射
1.3.1 反射的思想
如果对象的属性值要支持可扩展,那么属性的值我们就不能够在代码中去指定,必须通过某种方法分离出来,反射其实也是一种解耦的思想。
1.3.2 什么是反射
java的反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用他的任意一个方法和属性;这种动态获取信息以及动态调用对象方法的功能成为java语言的反射机制。
想要使用反射机制,就必须要先获取到该类的字节码文件对象(.class),通过字节码文件对象,就能够通过该类中的方法获取到我们想要的所有信息(方法,属性,类名,父类名,实现的所有接口等等),每一个类对应着一个字节码文件也就对应着一个Class类型的对象,也就是字节码文件对象。
获取字节码文件对象的三种方式:
Class clazz1 = Class.forName("全限定类名");
通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
例如:Class clazz0=Class.forName("com.lemon.day13.section01.Student");
Class clazz2 = 类名.class;
当类被加载成.class文件时,此时这个类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
例如:Class clazz=Student.class;
Class clazz3 = p.getClass();
通过类的实例获取该类的字节码文件对象,该类处于创建对象阶段。
有了字节码文件对象才能获得类中所有的信息,我们在使用反射获取信息时,也要考虑使用上面哪种方式获取字节码对象合理,视不同情况而定。
反射详解:.html
1.3.3 xml解析代码
这里解析的是课程中关于调用student类,为其设置属性值的方法:
1.3.4 通过字节码可以使用的方法
以下方法比较重要,需掌握:
需掌握:
具体使用:
1.4 HashMap和HashSet
详见我的这篇博文:
1.5 File类和IO类
传送门:
1.6 log4j的使用
传送门:
2. 正则表达式
这个博客讲得很好:
=1588848792548192879&wfr=spider&for=pc
3.XML
- xml:可扩展标记语言,在项目中的使用更多的是作为数据载体出现。
- xml和json都是一种数据交互格式。
- 所有元素有开始就有结束
- 大小写敏感
- 嵌套使用
- 更多的作为数据载体而出现。
- 非常适合万维网数据传输,提供统一方法描述和交换结构化数据
- xml声明:
- <?xml version="1.0" encoding="UTF-8"?>
- xml 中必须包含根元素,他是其他元素的父类型,下列实例中students就是一个根元素:
<students><student id="1"><name>honghong1</name><age>20</age><classsname>java82</classsname><gender>男</gender></student>
</students>
- xml文档结构:
- 和HTML类似,是一种树形结构从上至下扩展。
- 使用父、子、同胞等术语来表示元素之间的关系。
- 所有的元素都可以有文本内容和属性
- xml的语法和注释
- 属性必须用双引号“” 引起来
- 注释: 选中要注释的内容,然后点击
<!-- ctrl+shift+/ -->
3.1 dom4j
dom4j是一个Java的XML API。
我们打开maven 中央仓库,在其中搜索dom4j,选择1.6.1版本。
3.2 dom4j解析技术
用来解析xml中的数据,例如:
<students><student id="1"><name>honghong1</name><age>20</age><classsname>java82</classsname><gender>男</gender></student>
</students>
将这个xml中的数据进行解析,使用方法:
//new一个工具类SAXReader saxReade=new SAXReader();//读取这个文件-->文档-->提取信息Document document = saxReade.read(XmlReader.class.getResourceAsStream("/students.xml"));//类路径下根路径//获得根元素Element rootelement = document.getRootElement();//获得根节点的所有子节点List<Element> elements = rootelement.elements();for (Element element : elements) {//获得student子元素的id属性Attribute idattribute = element.attribute("id");//获得student元素的所有子元素List<Element> stuSubElements=element.elements();for (Element stuSubElement : stuSubElements) {//获得每个标签的名称System.out.println(stuSubElement.getName());//获得每个标签中的值System.out.println(stuSubElement.getText());}}
4. JDBC
4.1 什么是JDBC以及一些基础的SQL语句
JDBC:Java数据库连接(Java DataBase Connectivity)
用于执行SQL语句的Java API,Java语言编写的类和接口,为多种关系数据库提供统一访问。
4.1.1 创建表
// id、user_name,phone,pwd -- sql 大小写不区分--》弱语法
create table member(id in(10),user_name varchar(20),phone char(11),pwd varchar(40)
);
4.1.2 插入行
insert into 表名(需要添加值的字段) values(每个字段的值);insert INTO test(name,phone,sex) VALUES ("enna",MD5("13111111"),"nan")
4.1.3 删除行
-
删除表的所有记录
delete from 表名;
-
删除部分记录
delete from 表名 where 指定的条件;
-
删除整个表的记录(删除所有记录,而且会把自增长恢复到默认值)
truncate table member;
-
删除表(破坏性,谨慎操作,删除结构)
drop table member;
4.1.4 更新数据
update member set 字段1='新的值',字段2='新值'
4.1.5 查询数据
select 检索的字段 from 表名;
4.1.6 连接
-- 多表查询
-- 查询出来45条记录,叫做笛卡尔积
SELECT * FROM t_user,t_lover_info;
-- 想要筛选出有意义的记录
-- 等值连接
SELECT * FROM t_lover_info as t1,t_user as t2 WHERE t1.u_id=t2.id
SELECT * FROM t_lover_info as t1 JOIN t_user as t2 ON t1.u_id=t2.id
-- 内连接或等值连接,可以获取两个表中字段匹配关系的记录
SELECT * FROM t_lover_info as t1 INNER JOIN t_user as t2 ON t1.u_id=t2.id
SELECT * FROM t_lover_info as t1 CROSS JOIN t_user as t2 ON t1.u_id=t2.id--左连接,会读取左表的全部数据,即使右表没有对应数据。左连接从左表(A)产生一套完整的记录和右表匹配的记录,如果右表没有匹配记录,右侧结果集字段将为null
SELECT * FROM t_lover_info as t1 LEFT JOIN t_user as t2 ON t1.u_id=t2.id
-- 右连接是以右表为基础,与LEFT JOIN相反
SELECT * FROM t_lover_info as t1 RIGHT JOIN t_user as t2 ON t1.u_id=t2.id
其他sql语句的应用可以参考此前的博客:
4.2 工具 Navicat Premium 的下载与破解
Navicat Premium v12.1.9破解版_x86_x64:
软件破解补丁:
12.x最新版本:.exe
为了防止其中的软件及补丁分享失效,我在csdn上也已经上传了这两个软件的打包,链接:
破解过程:卸载掉早期版本,卸载干净,然后安装最新版navicat,安装完成后将破解补丁复制到安装目录下,运行破解补丁,先patch;
然后选择版本和语言;
运行navicat,弹出注册界面,如果没有弹出注册界面,手动在菜单打开:帮助->注册,然后点击注册机的generate按钮,注册码会自动填写到navicat;点击navicat注册界面的激活按钮,提示手动激活;
点击手动激活。
然后将得到的RequestCode复制到注册机;
点击注册机左下方的Generate按钮,生成ActivationCode,复制粘贴到navicat的激活码框,完成激活;
4.3 操作步骤
- 注册一个驱动
//这一步首先要在maven或者程序中引入mysql-connector.jarClass.forName("com.mysql.jdbc.Driver");
注意:
如果你在这里使用的是最新的mysql 连接驱动,那么驱动这里需要修改一下,否则会报异常:
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
解决方法:
将以上代码改为:
Class.forName("com.mysql.cj.jdbc.Driver");
- 连接数据库
String user = "futurevistor";String password = "123456";//jdbc是指使用mysql连接数据库,各个数据库管理工具使用的语法各不相同String url = "jdbc:mysql://120.78.128.25:3306/future";//DriverManager:负责访问数据库的驱动管理//Connection:与数据库进行连接的连接对象,所有与数据库的通信都是通过连接对象Connection conn = DriverManager.getConnection(url, user, password);
- 准备一个sql语句(这里以一个select语句为例)
String sql = "select * from member;";
- 使用一个对象来封装SQL并执行
PreparedStatement pstmt = conn.prepareStatement(sql);
- 执行这个sql语句,得到一个结果集
ResultSet resultSet=pstmt.executeQuery();while (resultSet.next()) {String id=resultSet.getString(1);String regName=resultSet.getString(2);String pwd1=resultSet.getString(3);String phone=resultSet.getString(4);System.out.println(id+" , "+regName+" , "+pwd1+" , "+phone);}
- 关闭连接
pstmt.close();conn.close();
注: 其中PreparedStatement处理的步骤:
代码如下:
String sql = "select * from member_water where mmobilephone=? and pwd=?;";PreparedStatement pstmt = conn.prepareStatement(sql);//对占位符对应的参数进行设值,mobilePhone和pwd为传入的参数pstmt.setString(1, mobilePhone);pstmt.setString(2, pwd);
4.4 写一个简单的DBUtil框架
/*** JDBC工具类,提供增删改查* @author mayn**/
public class DBUtil {/*** 0.注册驱动、连接数据库的而字符串代码冗余 1)只注册一遍 2)连接数据库的信息值声明一遍 1.重复的数据库的创建和关闭,形成资源的浪费* 2.增删改查语法不具备通用性(没办法适用所有表、所有的增删改查数据)* * @param args* @throws Exception*/private static String user;private static String password;private static String url;private static String driver;/*** 静态代码块,只运行一次,用于编写一些只需要运行一边的代码逻辑 通过静态库,保证注册驱动,以及读取数据库连接信息的操作只运行一遍*/static {try {Class.forName("com.mysql.jdbc.Driver");Properties properties = new Properties();properties.load(DBUtil.class.getResourceAsStream("/jdbc.properties"));driver = properties.getProperty("jdbc.driver");user = properties.getProperty("jdbc.user");password = properties.getProperty("jdbc.password");url = properties.getProperty("jdbc.url");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}public static void main(String[] args) throws Exception {// insert("kaibin", "hhhh", "13255555555");}private static Connection getConnection() throws SQLException {Connection conn = null;try {conn = DriverManager.getConnection(url, user, password);} catch (Exception e) {e.printStackTrace();}return conn;}/*** 不确定参数的类型和个数*/public static void execute(String sql, Object... params) {Connection conn = null;PreparedStatement pstmt = null;try {conn = getConnection();pstmt = conn.prepareStatement(sql);int length = params.length;for (int i = 0; i < length; i++) {pstmt.setObject(i + 1, params[i]);}pstmt.execute();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {close(conn, pstmt);}}/*** * @param sql* 要执行的sql语句* @param params* 占位符对应的参数* @return* @throws Exception*/public static List<Map<String, String>> select(String sql, Object... params){Connection conn=null;PreparedStatement pstmt =null;List<Map<String, String>> datalist =null;ResultSet resultSet = null;try {conn = getConnection();pstmt = conn.prepareStatement(sql);// 进行占位符的设值for (int i = 0; i < params.length; i++) {pstmt.setObject(i + 1, params[i]);}resultSet = pstmt.executeQuery();// 获得结果集的元数据ResultSetMetaData metaData = resultSet.getMetaData();// 获得列数,就是字段的数量int columnCount = metaData.getColumnCount();// 创建一个list存放所有的记录datalist = new ArrayList<Map<String, String>>();while (resultSet.next()) {// 创建一个mao对象,保存每一行数据Map<String, String> rowDataMap = new HashMap<String, String>();for (int i = 0; i < columnCount; i++) {// 获得每一列的值String value = resultSet.getString(i + 1);// 获得字段名使之为keyString columnName = metaData.getColumnName(i + 1);rowDataMap.put(columnName, value);}// 此时每一行的数据已经保存完毕,将这个hashmap放到list中datalist.add(rowDataMap);}} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {close(conn, pstmt, resultSet);}return datalist;}private static void close(Connection conn, PreparedStatement pstmt, ResultSet resultSet) {if(resultSet!=null){try {resultSet.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}close(conn, pstmt);}/*** 关闭资源* @param conn 连接* @param pstmt 陈述对象*/private static void close(Connection conn, PreparedStatement pstmt) {if (pstmt != null) {try {pstmt.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if (conn != null) {try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}
其中还包含一个jdbc.properties:
jdbc.url=jdbc:mysql://120.78.128.25:3306/future
jdbc.user=futurevistor
jdbc.password=123456
jdcc.driver=com.mysql.cj.jdbc.Driver
写完之后,只需要传入sql语句和可变参数就可以直接调用并进行增删改查操作了,例:
//新建了一个DBTest类用来测试框架是否可用
public class DBTest {public static void main(String[] args) throws Exception {//1.测试插入:
// String sql="insert into member_water(regname,mobilephone,pwd,leaveamount) value(?,?,?,?);";
// DBUtil.execute(sql, "kaibin","13212575740","123456",100.0);//修改
// String sql="update member_water set leaveamount=? where id=?";
// DBUtil.execute(sql,10.0,41);//删除
// String sql="delete from member_water where id=?";
// DBUtil.execute(sql, 41);//查询String sql="select * from member_water ";List<Map<String, String>> data=new ArrayList<Map<String,String>>();data=DBUtil.select(sql);for (Map<String, String> map : data) {System.out.println(map);}}}
5.TestNG
5.1 单元测试的概念
- 单元测试(unit testing),是指对软件中的最小可测试单元(方法、函数)进行检查和验证。
- 单元测试是开发者编写的一小段代码,用于检测被测代码的一个很小的、很明确的功能(方法、函数)是否正确
- 单元测试是由程序员自己来完成,程序员有责任编写功能代码,同时也就有责任为自己的代码编写单元测试
- 通常而言,一个单元测试适用于判断某个特定条件下某个特定函数的行为。
- 执行单元测试就是为了证明这段代码的行为和我们的预期一致
5.2 TestNG的安装
Testing Next Generation,下一代测试技术。
利用注解来强化测试功能的测试框架,可以用来做单元测试和集成测试。
首先将testNG插件放到eclipse对应的文件夹下,testNG插件下载:
链接:
提取码:waob
将插件安装成功后,右键就能够在菜单中看见testNG。
5.3 项目集成testNG
- 项目集成testNG,加入依赖库
<dependency><groupId>org.testng</groupId><artifactId>testng</artifactId><version>6.8.8</version><scope>test</scope>
</dependency>
- 选中testNG.xml执行测试套件时,可能会碰到ElementTravelsal找不到的问题:
<dependency><groupId>xml-apis</groupId><artifactId>xml-apis</artifactId><version>1.4.01</version>
</dependency>
5.4 testNG的书写和运行
testNG的两种执行方式:
- 书写单独的测试类
我们可以书写单独的测试类,然后右键–>Run As–>TestNG Test,然后在下面的Results中查看运行结果。 - 书写一个TestNG Suite
例如:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM ".0.dtd" >
<suite name="Suite" parallel="false"><test name="login_test"><classes><class name="day16.Login_Failure_Test"/><class name="day16.Login_Success_Test"/></classes></test> <!-- Test --><test name="register_test"><classes><class name="day16.Register_Failure_Test"/><class name="day16.Register_Success_Test"/></classes></test> <!-- Test -->
</suite> <!-- Suite -->
<!--
1.suite->套件-》某个模块、整个系统所有的测试用例
2.test-》测试-》登录模块、注册模块
3.classes-》这个测试中间的测试类-》登陆成功的一个类,登陆失败的一个类-->
然后右键testng.xml–>Run As–>TestNG Suite,然后可以在控制台和Results of running suite中分别查看结果。
5.5 eclipse 乱码问题
如果遇到eclipse乱码的问题,在eclipse.ini文件中添加:-Dfile.encoding=UTF-8
5.6 testNG中一些常用的注解
- 忽略测试
当我们在测试的过程中,因为某些方面的原因,比如测试方法没有写完,或者是有问题,我们暂时希望它不执行,我们就可以添加忽略标签来跳过此方法的运行。
@Test(enable=false)
- 超时测试
表示如果单元测试花费的时间超过制定的毫秒数,那么testNG将会中止它并将其标记为失败。这样在某些业务场景之下,我们认为一个请求时间过长就可以直接宣判他因为超时而失败。
@Test(timeOut=1000)
- 异常测试(使用较少)
测试代码中有没有抛出我预测的这个异常。如果没有expectedExceptions列表中的异常抛出,或者抛出的异常不属于列表中的异常都无法通过。
@Test(expectedExceptions={NullPointerException.class,ClassNotFoundException.class})
- 依赖测试
dependsOnMethods:这个的测试方法依赖于某些方法
@Test(dependsOnMethods={"e","d"})
方法的执行顺序:
- 先执行被依赖的方法
- 在依次执行没配置依赖的方法
- 最后执行需要依赖的测试方法
dependsOnGroups:这个的测试方法依赖于某些组
- 分组测试
只想执行某一部分或者个别的测试用例
- 测试用例方法指定所属分组:groups
- 在testng.xml的test中指定相应的测试类
- 在test的groups里面指定run下要执行的分组
- 当测试用例越来越多,某些分组不想执行,设置的方法也一样:在test的groups里面指定run选不需要执行的分组
语法:
测试方法属于哪一个分组:
@Test(groups={"g1,g2"})
此测试方法属于g1分组,但是依赖于g2分组:
@Test(dependsOnGroups={"g2"},groups={"g1"})
只会执行g1组的测试方法,其他测试方法都不会执行:(写在.xml文件中)
<groups><run><!-- 只执行g1组 --><include name="g1"></include><!-- 不执行g1组 --><exclude name="g1"></exclude></run></groups>
- 优先级设置
后面的整数数字越低,优先级越高。
@Test(priority=1)
还要在.xml文件中开启
<test name="Test" preserve-order="true">
5.7 TestNG 执行 junit 测试
testNG提供了一种配置方式使得我们不需要去重构已经写好的junit单元测试类:
在testNG.xml中添加一个test,将junit属性设置为true即可:
<test name="testJunitClass" junit="true"><classes><class name="xx.yy.aa.JunitDemo" /></classes></test>
5.8 断言
5.9 数据驱动(Data Provider)
public class DataProviderTest {//表示由方法“dp”来注入数据,也叫数据驱动@Test(dataProvider = "dp")public void f(Integer n, String s,String name) {System.out.println(n+","+s+","+name);}//下面的这个方法是为测试单元测试方法提供数据的@DataProviderpublic Object[][] dp() {return new Object[][] {new Object[] { 1, "a","tom" },new Object[] { 2, "b" ,"jack"},new Object[] { 3, "a" ,"kaibin"},new Object[] { 4, "b" ,"honghong"},};}
}
最后总结一下:
如果你对此文有任何疑问,如果你也需要接口项目实战,如果你对软件测试、接口测试、自动化测试、面试经验交流感兴趣欢迎加入:软件测试技术群:593462778,群里的免费资料都是笔者十多年测试生涯的精华。还有同行大神一起交流技术哦。
作者:暗潮汹涌
原创不易,欢迎转载,但未经作者同意请保留此段声明,并在文章页面明显位置给出原文链接。
本文标签: JAVA关于自动化测试所需要学习的java基础知识笔记
版权声明:本文标题:【JAVA】关于自动化测试所需要学习的java基础知识笔记 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1688191592h190179.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论