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类型的对象,也就是字节码文件对象。

获取字节码文件对象的三种方式:

  1. Class clazz1 = Class.forName("全限定类名");
    通过Class类中的静态方法forName,直接获取到一个类的字节码文件对象,此时该类还是源文件阶段,并没有变为字节码文件。
例如:Class clazz0=Class.forName("com.lemon.day13.section01.Student");
  1. Class clazz2 = 类名.class;
    当类被加载成.class文件时,此时这个类变成了.class,在获取该字节码文件对象,也就是获取自己, 该类处于字节码阶段。
例如:Class clazz=Student.class;
  1. 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

  1. xml:可扩展标记语言,在项目中的使用更多的是作为数据载体出现。
  • xml和json都是一种数据交互格式。
  • 所有元素有开始就有结束
  • 大小写敏感
  • 嵌套使用
  • 更多的作为数据载体而出现。
  • 非常适合万维网数据传输,提供统一方法描述和交换结构化数据
  1. xml声明:
  • <?xml version="1.0" encoding="UTF-8"?>
  1. xml 中必须包含根元素,他是其他元素的父类型,下列实例中students就是一个根元素:
<students><student id="1"><name>honghong1</name><age>20</age><classsname>java82</classsname><gender>男</gender></student>
</students>
  1. xml文档结构:
  • 和HTML类似,是一种树形结构从上至下扩展。
  • 使用父、子、同胞等术语来表示元素之间的关系。
  • 所有的元素都可以有文本内容和属性
  1. 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 删除行
  1. 删除表的所有记录

    delete from 表名;

  2. 删除部分记录

    delete from 表名 where 指定的条件;

  3. 删除整个表的记录(删除所有记录,而且会把自增长恢复到默认值)

    truncate table member;

  4. 删除表(破坏性,谨慎操作,删除结构)

    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 操作步骤

  1. 注册一个驱动
	//这一步首先要在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");
  1. 连接数据库
		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);
  1. 准备一个sql语句(这里以一个select语句为例)
	String sql = "select * from member;";
  1. 使用一个对象来封装SQL并执行
	PreparedStatement pstmt = conn.prepareStatement(sql);
  1. 执行这个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);}
  1. 关闭连接
		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的两种执行方式:

  1. 书写单独的测试类
    我们可以书写单独的测试类,然后右键–>Run As–>TestNG Test,然后在下面的Results中查看运行结果。
  2. 书写一个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中一些常用的注解

  1. 忽略测试
    当我们在测试的过程中,因为某些方面的原因,比如测试方法没有写完,或者是有问题,我们暂时希望它不执行,我们就可以添加忽略标签来跳过此方法的运行。
@Test(enable=false)
  1. 超时测试
    表示如果单元测试花费的时间超过制定的毫秒数,那么testNG将会中止它并将其标记为失败。这样在某些业务场景之下,我们认为一个请求时间过长就可以直接宣判他因为超时而失败。
@Test(timeOut=1000)
  1. 异常测试(使用较少)
    测试代码中有没有抛出我预测的这个异常。如果没有expectedExceptions列表中的异常抛出,或者抛出的异常不属于列表中的异常都无法通过。
@Test(expectedExceptions={NullPointerException.class,ClassNotFoundException.class})
  1. 依赖测试
    dependsOnMethods:这个的测试方法依赖于某些方法
@Test(dependsOnMethods={"e","d"})

方法的执行顺序:

  • 先执行被依赖的方法
  • 在依次执行没配置依赖的方法
  • 最后执行需要依赖的测试方法

dependsOnGroups:这个的测试方法依赖于某些组

  1. 分组测试
    只想执行某一部分或者个别的测试用例
  • 测试用例方法指定所属分组: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>
  1. 优先级设置
    后面的整数数字越低,优先级越高。
@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基础知识笔记