白盒测试又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。
它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。 这一方法是把测试对象看作一个打开的盒子,测试人员依据程序内部逻辑结构相关信息,设计或选择测试用例,对程序所有逻辑路径进行测试,通过在不同点检查程序的状态,确定实际的状态是否与预期的状态一致。
白盒测试是一种测试用例设计方法,盒子指的是被测试的软件,白盒指的是盒子是可视的,你清楚盒子内部的东西以及里面是如何运作的。
"白盒"法全面了解程序内部逻辑结构、对所有逻辑路径进行测试。测试者必须检查程序的内部结构,从检查程序的逻辑着手,得出测试数据。
单元测试属于白盒测试。
在你不知道如何测试代码前,就不要写代码去完成功能 —> 测试先行
Java的单元测试:Junit 目前存在三个版本
- junit3.x:针对于Java5 之前的版本,没有注解,得按照规范来写测试。
- junit4.x:针对于Java5 以后的版本,使用注解。
- junit5.x:针对于 Java8 以后的版本。
我们这里就是对单元测试有个简单认识,会简单利用 3 和 4 编写一些测试代码。
测试环境搭建:将 junit 的测试 jar,添加到该项目中。
使用 junit3.x(了解)
junit3.x 是 Java5 以前的测试方式。
测试步骤:
- 把 junit3.x 的测试 jar,添加到项目中;
- 定义一个测试类,并让该测试类继承
TestCase
;
测试类的名字:XxxTest
,Xxx
表示一个对象或者一个模块、组件。 - 在
EmployeeDAOTest
中编写测试方法;
方法是public
修饰,无返回值、无参数的。
必须以test
作为方法的前缀,Xxx
表示测试的功能名字。
public void testXxx() throws Exception {}
- 选择某一个测试方法,鼠标右键选择 [run as junit];
或者选中测试类,表示测试该类中所有的测试方法。
- 若要在测试方法之前做准备操作:
EmployeeDAOTest
覆写TestCase
中protected void setUp() throws Exception
方法; - 若要在测试方法之后做回收操作:
EmployeeDAOTest
覆写TestCase
中protected void tearDown() throws Exception
方法; - 测试执行顺序:
setUp
-> 测试方法 ->tearDown
->setUp
-> 测试方法2 ->tearDown
…
示例:利用 JUnit3 编写 EmployeeDAOTest
的测试类。
package com.yusael._01_junit.junit3; import junit.framework.TestCase; // EmployeeDAO组件的测试类 public class EmployeeDAOTest extends TestCase { @Override // 初始化操作 protected void setUp() throws Exception { System.out.println("初始化操作"); } @Override // 销毁操作 protected void tearDown() throws Exception { System.out.println("销毁操作"); } // 测试员工的保存操作 public void testSave() throws Exception { System.out.println("保存测试"); } // 测试员工的删除操作 public void testDelete() throws Exception { System.out.println("删除测试"); } }
使用 junit4.x(掌握)
junit4.x 基于 Java5 开始的版本,支持注解。
步骤:
- 把 junit4.x 的测试 jar,添加到项目中;;
- 定义一个测试类。(不再继承
TestCase
类)
测试类的名字:XxxTest
- 在
EmployeeDAOTest
中编写测试方法;
方法是public
修饰的,无返回的;
该方法上必须贴有@Test
标签,Xxx
表示测试的功能名字。
@Test public void testXxx() throws Exception {}
- 选择某一个测试方法,鼠标右键选择 [run as junit];
或者选中测试类,表示测试该类中所有的测试方法。
以后单元测试使用最多的方式:
- 若要在测试方法之前做准备操作:
EmployeeDAOTest
随意定义一个方法并使用@Before
标注;
每次执行测试方法之前都会执行@Before
标注的方法
@Before public void xx() throws Exception {}
- 若要在测试方法之后做回收操作:
EmployeeDAOTest
随意定义一个方法并使用@After
标注;
每次执行测试方法之后都会执行@After
标注的方法;
@After public void xx() throws Exception {}
- 有没有方式只初始化一次,和最终只销毁一次呢?
@BeforeClass
标签:在所有的Before
方法之前执行,只在最初执行一次, 只能修饰静态方法。@AfterClass
标签:在所有的After
方法之后执行,只在最后执行一次,只能修饰静态方法。 - 测试执行顺序:
BeforeClass
-> (Before
->Test
->After
-> … ) ->AfterClass
示例:利用 JUnit4 编写 EmployeeDAOTest
的测试类。
package com.yusael._01_junit.junit4; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; // EmployeeDAO组件的测试类 public class EmployeeDAOTest { @BeforeClass public static void staticInit() throws Exception { System.out.println("static - Init"); } @AfterClass public static void staticDestroy() throws Exception { System.out.println("static - Destroy"); } @Before public void Init() throws Exception { System.out.println("初始化操作"); } @After public void Destory() throws Exception { System.out.println("销毁操作"); } @Test public void testSave() throws Exception { System.out.println("保存测试"); } @Test public void testDelete() throws Exception { System.out.println("删除测试"); } }
使用断言方式(了解)
这个不是很常用,只需要了解即可。
期望值: 断言时希望是多少。
真实值: 程序内部运算之后实际是多少。
断言成功: 期望值和真实值相同,此时显示绿条。
断言失败: 期望值和真实值不同,此时显示红条。
断言:
Assert.assertEquals(message, expected, actual)
:比较的值
message:断言失败的提示信息,断言成功不会显示
expected:期望值
actual:真实值
若真实值和期望值想等,则断言成功 —> 绿条Assert.assertSame(message, expected, actual)
:比较地址,断言是同一个对象Assert.assertNotSame(message, expected, actual)
:断言不是同一个对象Assert.assertTrue(message, condition)
:断言 condition 应该为 TRUEAssert.assertFalse(message, condition)
:断言 condition 应该为 FALSEAssert.assertNull(message, object)
:断言对象 object 为 nullAssert.assertNotNull(message, object)
:断言对象 object 不为 null@Test(expected=ArithmeticException.class)
:期望该方法抛出ArithmeticException
异常@Test(timeout=400)
:期望该方法在400毫秒之内执行完成
示例:利用断言进行对数学方法类进行测试。
package com.yusael._01_junit.asserted; /** * 数学运算功能 * @author yusael */ public interface IMath { /** * 两个数相加 * @param a 加数 * @param b 加数 * @return 两个数之和 */ int add(int a, int b); /** * 两个数之商(考虑整除) * @param a 被除数 * @param b 除数 * @return 商 */ int divide(int a, int b); }
package com.yusael._01_junit.asserted.impl;
import com.yusael._01_junit.asserted.IMath;
public class MathImpl implements IMath {
@Override public int add(int a, int b) { return a + b; } @Override public int divide(int a, int b) { return a / b; }
}
package com.yusael._01_junit.asserted; import org.junit.Test; import com.yusael._01_junit.asserted.impl.MathImpl; import junit.framework.Assert; // Math测试类 public class MathTest { // 依赖关系 private IMath math = new MathImpl(); @Test public void testAdd() { int ret = math.add(1, 2); Assert.assertEquals(3, ret); } @Test public void testDivide() { int ret = math.divide(6, 2); Assert.assertEquals(3, ret); } // 期望抛出ArithmeticException异常, 不抛则测试不通过 @Test(expected=ArithmeticException.class) public void testException() { math.divide(2, 0); // 抛出ArithmeticException异常, 测试通过 } } ``` ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429192925423.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://blog.csdn.net/weixin_43734095/article/details/105845863)XML 以及约束 =========================================================================== **XML(eXtensible Markup Language)**,是一种可扩展的标记语言,类似 HTML。 > XML技术是W3C组织(World Wide Web Consortium万维网联盟)发布的,目前遵循的是W3C组织于2000年发布的XML1.0规范。 > XML被广泛认为是继Java之后在Internet上最激动人心的新技术。 > XML的树状结构简单,清晰,无论是人还是计算机都能轻松解析。 > XML作为一种公订的、开放的标准,不受知识产权的限制。 HTML: 显示页面,网页. 学习里面自带的标签 **XML**: **传输数据,而非显示数据**。 XML标签没有被预定义,需要用户自行定义标签。 为什么要学XML: * XML是一种通用的数据交换格式; * 许多项目都采用XML作为数据交换格式; * 掌握XML是软件开发人员的一项基本技能; Struts、Spring、Hibernate、Mybatis 等任意一个 Java EE 框架中都可用XML做配置文件。 [](https://blog.csdn.net/weixin_43734095/article/details/105845863)XML语法 ------------------------------------------------------------------------ XML有两个编码: **内容编码、文件本身的编码**;要保证两个编码相同,都为 UTF-8。 一个XML文档必须**有且仅有一个根标签**,**不允许标签嵌套**,**区分大小写**。 在编写XML文档时, * 需要先使用文档声明来声明XML文档,且必须出现在文档的第一行。 最简单的语法,如:`<?xml version="1.0"?>` * 用 `encoding` 属性说明文档所使用的字符编码,默认为 UTF-8。 保存在磁盘上的文件编码要与声明的编码一致。 如:`<?xml version="1.0" encoding="UTF-8"?>` * 用 `standalone` 属性说明文档是否独立,即是否依赖其他文档。 如:<?xml version=”1.0” standalone=”yes”?> `CDATA` 是 Character Data 的缩写: * 作用:把标签当做普通文本内容; 解析器不对 `CDATA` 区中的内容进行解析,而是将这些数据原封不动地交给程序去处理。 * 语法:`<![CDATA[数据内容]]>` **xml 一般情况下不会要求去写,大致看得懂即可**。 ``` <?xml version="1.0" encoding="UTF-8"?> <contacts> <linkman id="1"> <name>Will</name> <email>iwiller@qq.com</email> <address>成都</address> <group>叩丁狼教育</group> </linkman> <linkman id="2"> <name>Stef</name> <email>lanyotech@qq.com</email> <address>成都</address> <group>叩丁狼教育</group> </linkman> </contacts> ``` [](https://blog.csdn.net/weixin_43734095/article/details/105845863)DTD 约束(了解) ----------------------------------------------------------------------------- ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200430002106810.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://blog.csdn.net/weixin_43734095/article/details/105845863)Scheme 约束(了解) -------------------------------------------------------------------------------- ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429205532710.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://blog.csdn.net/weixin_43734095/article/details/105845863)DOM ====================================================================== **DOM(Document Object Model)**:文档对象模型 * 使用面问对象的方式,把 XML 文件中的结构使用对象来表示。 在 XML 中,一切皆节点(Wode)。 * **Node**:节点 * **Document**:文档节点(XML 文件) * **Element**:元素节点(使用 <> 表示标签) * **Attribute**:属性节点(元素上属性名 = “属性值”) * **Text**:文本节点(元素之间的内容) ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429233849489.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429233912238.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) [](https://blog.csdn.net/weixin_43734095/article/details/105845863)获取Document文档对象 --------------------------------------------------------------------------------- **DOM(Document Object Model)**:文档对象模型 * 使用面问对象的方式,把 XML 文件中的结构使用对象来表示。 使用 Java 代码操作 XML **使用 JavaScript 操作 HTML** **特点**: * 在加载的时候,一次性把整个XML文档加载进内存,在内存中形成一颗树对象(Document )。 * 我们以后使用代码操作 Document,其实操作的是内存中的 DOM 树;和本地磁盘中的XML文件没有直接关系。 * 比如:我保存了一个联系人,仅仅是内存中多了一个联系人,但是在XML文件中没有新增的痕迹。除非做 **同步操作**:把内存中的数据更新到XML文件。( 增删改操作完之后,都需要做**同步操作**。) * 缺点:若XML文件过大,可能造成**内存溢出**。 **获取 Document 文档对象**: ``` package com.yusael._03_dom; import java.io.File; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.junit.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; // DOM操作测试类 public class DOMTest { private File f = new File("F:/java/JavasePro/JUnit-XML-DOM-DOM4J/contacts.xml"); // 如何获取Document文档对象 @Test public void testGetDocument() throws Exception { // 1):创建DocumentBuilderFactory对象(意识:工厂类中一般都有一个静态方法用于返回当前工厂类对象) DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); // 2):根据工厂对象, 创建DocumentBuilder对象 DocumentBuilder builder = factory.newDocumentBuilder(); // 3):根据builder对象去解析一个已经存在的XML文件, 从而得到Document对象. Document doc = builder.parse(f); // [#document: null] } } ``` ![在这里插入图片描述](https://ucc.alicdn.com/images/user-upload-01/20200429235333652.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzczNDA5NQ==,size_16,color_FFFFFF,t_70) 根据 `DocumentBuilder` 创建 `Document` 对象,有两种方式: * 当XML文档不存在时,使用 `newDocument()`,在内存中先创建出一颗 树对象(Document)。 ``` Document doc=builder.newDocument(); ``` * 当XML文档存在时,我们只需要**直接解析**即可。 ``` Document doc = builder.parse(File对象); ``` 什么是**解析**(parse):一般而言,把使用 String 描述的事物,转换为描述该事物的类型。 ``` // 解析时间 Date d = DateFormat对象.parse("2018-10-10"); ``` [](https://blog.csdn.net/weixin_43734095/article/details/105845863)得到某个具体的文本节点的内容:取出第二个联系人的名字 --------------------------------------------------------------------------------------------- 操作步骤: 1. 获取 `Document` 文档对象 2. 获取 XML 中的根元素 `contacts` 3. 获取第二个联系人元素 `linkman` 4. 获取 `linkman` 元素下的 `name` 子元素 5. 获取 `name` 元素的文本内容 ``` // 需求1、得到某个具体的文本节点的内容:取出第二个联系人的名字. @Test public void test1() throws Exception { // 1):获取Document文档对象. Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(f); // 2):获取XML中的根元素(contacts). Element root = doc.getDocumentElement(); // 3):获取第二个联系人元素(linkman). Element linkmanEl = (Element)root.getElementsByTagName("linkman").item(1); // 4):获取linkman元素下的name子元素. Element nameEl = (Element)root.getElementsByTagName("name").item(0); // 5):获取name元素的文本内容. System.out.println(nameEl.getTextContent()); } ``` [](https://blog.csdn.net/weixin_43734095/article/details/105845863)修改某个元素节点的主体内容:把第一个联系人的邮箱改掉 --------------------------------------------------------------------------------------------- 操作步骤: 1. 获取 `Document` 文档对象 2. 获取 XML 中的根元素 `contacts` 3. 获取第一个联系人元素 `linkman` 4. 获取 `linkman` 元素下的 `email` 子元素 5. **设置 `email` 元素的新的文本内容 `will@`** 6. **同步操作**:把内存中的数据同步更新到磁盘的XML中 核心类:`Transformer` ``` // 需求2、修改某个元素节点的主体内容:把第一个联系人的邮箱改掉. @Test public void test2() throws Exception { # 总结 本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解! **重要的事:需要领取完整版的MySQL学习笔记的话,请转发+关注后[点这里免费获取](https://gitee.com/vip204888/java-p7)到免费的下载方式!** **MySQL50道高频面试题整理:** an元素下的name子元素. Element nameEl = (Element)root.getElementsByTagName("name").item(0); // 5):获取name元素的文本内容. System.out.println(nameEl.getTextContent()); } ``` [](https://blog.csdn.net/weixin_43734095/article/details/105845863)修改某个元素节点的主体内容:把第一个联系人的邮箱改掉 --------------------------------------------------------------------------------------------- 操作步骤: 1. 获取 `Document` 文档对象 2. 获取 XML 中的根元素 `contacts` 3. 获取第一个联系人元素 `linkman` 4. 获取 `linkman` 元素下的 `email` 子元素 5. **设置 `email` 元素的新的文本内容 `will@`** 6. **同步操作**:把内存中的数据同步更新到磁盘的XML中 核心类:`Transformer` ``` // 需求2、修改某个元素节点的主体内容:把第一个联系人的邮箱改掉. @Test public void test2() throws Exception { # 总结 本文从基础到高级再到实战,由浅入深,把MySQL讲的清清楚楚,明明白白,这应该是我目前为止看到过最好的有关MySQL的学习笔记了,我相信如果你把这份笔记认真看完后,无论是工作中碰到的问题还是被面试官问到的问题都能迎刃而解! **重要的事:需要领取完整版的MySQL学习笔记的话,请转发+关注后[点这里免费获取](https://gitee.com/vip204888/java-p7)到免费的下载方式!** **MySQL50道高频面试题整理:** ![](https://ucc.alicdn.com/images/user-upload-01/img_convert/7c3679d466694272a51d2fb9f24f2e32.png)