软件测试
目的:在规定的条件下,对程序进行操作,以发现程序错误,衡量软件质量,并对其是否满足设计要求进行评估的过程
测试分类
黑盒测试:软件的黑盒测试意味着测试要在软件的接口处进行,这种方法是把测试对象看作一个黑盒子,测试人员完全不考虑程序内部的逻辑结构和内部特性,只依据程序的需求规格说明书,检查程序的功能是否符合功能说明。因此,黑盒测试又称功能测试
白盒测试:软件的白盒测试是对软件的过程细节做细致的检查。这种方法是把测试对象看作一个打开的盒子,它允许测试人员利用程序内部的逻辑结构及有关信息,设计或选择测试用例,对程序的所有逻辑路径进行测试,通过在不同点检查程序状态,确定实际状态是否与预期的状态一致。因此,白盒测试又称结构测试。
没有junit测试时的缺陷
- 测试一定要走main方法,是程序的入口,main方法的格式必须不能写错
- 要是在同一个main方法中测试的话,那么不需要测试的东西必须注释掉
- 测试逻辑如果分开的话,需要定义多个测试类,麻烦
- 业务逻辑和测试代码都混淆了
关于测试
- 一般测试和业务分离,分离为不同的包,名字建议为:公司域名倒写 test,以后的测试类都放在这个包下
- 测试类的名字要见名知意
- 测试类可以独立运行,不依托于main方法
- 测试方法参数为无参,返回值为void
- 测试方法定义完后不能独立运行,必须要在方法前加注解@test并导入junit环境
- 判定结果(绿色:正常;红色:异常)
- 即使出现绿色效果,也不意味着测试通过,因为代码中可能出现问题,解决方法:加入断言
断言
语法:assert.assertequals(期望结果,实际结果);
作用:当期望结果与实际结果不符,那么就抛出异常
@test
public void testout(){
system.out.println("测试开启");
//0,1的随机数
long round = math.round(math.random());
//加入断言,若真实值不等于期望值则抛出异常
//第一个参数:预测结果 第二个参数:实际结果
assert.assertequals(1, round);
}
@before与@after
@before:某一测试方法中若加入了@before注解以后,那么此方法中的功能会在测试方法执行前先执行
@after:某一测试方法中若加入了@after注解以后,那么此方法中的功能会在测试方法执行后执行
public class test1 {
@before
public void init(){
system.out.println("测试方法开始了");
}
@after
public void close(){
system.out.println("测试方法结束了");
}
@test
public void test1(){
system.out.println("测试1执行中……");
}
@test
public void test2(){
system.out.println("测试2执行中……");
}
}
注解:注解其实就是代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取并执行相应的处理。通过使用注解,程序员可以在不改变原有逻辑的情况下,在源文件中嵌入一些补充信息。代码分析工具、开发工具和部署工具,可以通过这些补充信息进行验证或者进行部署
注解开发优势:现在主流开发都是基于注解方式,代码量少,框架可以根据注解去自动生成很多代码,从而减少代码量,程序更易读,如最火爆的springboot就是完全基于注解技术实现的。
注意:
- 使用注解时要在其前面加@符号,并把注解当成一个修饰符使用。用于修饰它支持的程序元素
- 注解一般和反射配套使用(就是一个标记,被读到便可修改相关内容)
注解分类
- jdk自带注解
- 元注解
- 自定义注解
jdk注解
- @override:用来标识此方法是重写的方法
- @deprecated:用于表示修饰的元素(类、方法、构造器、属性)已过时
- @suppresswarnings(“unused”)忽略警告(不仅可以放在类上也可以放在方法上)
- @safevararys:堆污染
元注解
含义:用来描述注解的注解
- @target:表明注解用在哪,类上?方法上?
- @retention:注解的生命周期(runtime>class>source)
- @inherited:父类加上该注解修饰的注解,那么子类也相当于加上该注解修饰的注解
- @documented:生成javadoc时会包含该注解
- @repeatable:注解为可重复型注解(就是可以在一个地方放多个)
自定义注解格式
@target({elementtype.method,elementtype.type})//可以加在方法&类上——用来表示元注解
@retention(retentionpolicy.runtime)//到运行时都有效
@interface 注解名{
属性类型 属性名1() [default 属性值1];
属性类型 属性名2() [default 属性值2];//[]内部的东西代表可以不写
}
//下面以rice注解为例
注意:
- 元注解应定义在注解上面
- 定义注解只能使用public/默认修饰符
- 注解内部的属性可以为0个或多个
- 内部没有定义参数的注解叫做标记,内部定义参数的注解叫做元数据
- 使用@interface自定义注解时,自动继承了java.lang.annotation.annotation接口
@target(属性)
属性值内部可选项:
- element.type:表明此注解可以用在类上
- element.method:表明此注解可以用在方法上
- element.field:表明此注解可以用在字段或属性上
- element.annotation_type:表明此注解可以用在注解类型上
- element.constructor:表明此注解可以用在构造函数上
- element.local_variable:表明此注解可以用在局部变量上
- element.package:表明此注解可以用在包声明上
- element.parameter:表明此注解可以用在方法的参数上
注意:
- 如果没规定使用位置的注解,则他放到哪都可以
- 注解在同包中有效,如果要在不同包中有效则需要设置public属性(一个源文件中只能有一个public类)
- 属性名为value,属性值为1个数组,如果有多个可选项那么总体用{}包裹起来(也可以写成value={})中间用逗号隔开
@retention(retentionpolicy.属性名)
属性名:
- source:在源文件中有效(当java文件编译成.class文件时被遗弃)
- class:在class文件中有效(当jvm加载class文件时被遗弃)
- runtime:在运行时都有效
注意:
- 属性名只能三选一
- 如果注解没有加@retention元注解,那么相当于默认的注解就是在class文件中有效
- 生命周期排序:runtime>class>source
注解的内部属性
注解属性的类型:基本数据类型、string类型、枚举类型、注解类型、以上类型的数组。
普通属性
注解属性的定义:int age();
注解的属性都可以设置默认值:int age() default 0;
数组类型注解属性定义
- 设置默认值:int[] ages() default {1,2,3,4,5,6};
- 不设置默认值:int[] age();
注意:
- 如果不设置默认值则使用注解时必须给其属性赋值eg:@rice(age=8)、eg:@rice(ages={1,2,3,4,5,6})
- 当有多个内部属性没有设置默认值是,要想使用注解,则需要将多个属性赋值,多个属性之间用逗号隔开
- 如果此属性有了默认值,同时在使用注解时也给此属性赋予了新值,则默认值会被新值覆盖。
特殊属性value
设置属性:
- 不设默认值:int value();
- 设置默认值:int value() default 0;
使用:
- 单个属性:@rice(value=5)可以简写成@rice(5)
- 多个属性:@rice(age=8,value=5)不能简写
注意:特殊属性的定义与别的属性相同,主要是使用方式不同(比如单个属性的话相对于普通属性可以简写,但是多个属性不行)
含义:一枚一枚的列举出来,但是个数是有限的、能穷尽的
自定义枚举类
定义枚举类
public class season {
//属性
private final string seasonname;//季节名字
private final string seasondesc;//季节描述
//利用构造器对属性赋值
//构造器私有化,外界不能调用这个构造器,只能season自己调用
private season(string seasonname,string seasondesc){
this.seasonname=seasonname;
this.seasondesc=seasondesc;
}
//提供枚举类有限的,确定的对象——外界可以通过类名直接调用获得对象
public static final season spring=new season("春天","春暖花开");
public static final season summer=new season("夏天","烈日炎炎");
public static final season autumn=new season("秋天","硕果累累");
public static final season winter=new season("冬天","冰天雪地");
//提供get方法,外界可以获取对象属性
public string getseasonname() {
return seasonname;
}
public string getseasondesc() {
return seasondesc;
}
@override
public string tostring() {
return "season{"
"seasonname='" seasonname '\''
", seasondesc='" seasondesc '\''
'}';
}
}
测试枚举类
public class test1 {
public static void main(string[] args) {
//获取枚举对象
season summer = season.summer;
system.out.println(summer.tostring());//season{seasonname='夏天', seasondesc='烈日炎炎'}
system.out.println(summer.getseasonname());//夏天
system.out.println(summer.getseasondesc());//烈日炎炎
}
}
enum关键字创建枚举类
枚举类结构(用例)
public enum season {
//提供枚举类有限的,确定的对象——外界可以通过类名直接调用获得对象——>enum枚举类要求对象放在最开始的位置上
spring("春天","春暖花开"),
summer("夏天","烈日炎炎"),
autumn("秋天","硕果累累"),
winter("冬天","冰天雪地");
//属性名
private final string seasonname;//季节名字
private final string seasondesc;//季节描述
//利用构造器对属性赋值
//构造器私有化,外界不能调用这个构造器,只能season自己调用
private season(string seasonname, string seasondesc){
this.seasonname=seasonname;
this.seasondesc=seasondesc;
}
//提供get方法,外界可以获取对象属性
public string getseasonname() {
return seasonname;
}
public string getseasondesc() {
return seasondesc;
}
}
注意:
- 以enum关键字定义枚举类
- 枚举类提供的枚举对象必须放在结构的最上面,并且多个对象之间用逗号隔开,最后的对象用分号结束
- 枚举对象可以通过类名.枚举对象名直接调用
- 枚举对象的属性可以通过get方法直接获取
- 以enum关键字定义的枚举类上层的父类为java.lang.enum,并且enum类对tostring方法进行了重写,重写后的tostring方法直接返回对应的枚举对象名
枚举类测试
public class test {
public static void main(string[] args) {
season autumn = season.autumn;
system.out.println(autumn);//autumn
system.out.println(autumn.getseasonname());//秋天
}
}
空参枚举对象的枚举类
public enum season {
//这里面一共4个枚举对象
spring,
summer,
autumn,
winter;
}
理解:因为此枚举类底层没有属性、构造器、get方法,本来枚举对象应写成对象名(),但是()在没有属性的情况下也可以省略
枚举类的常用方法
tostring
语法:枚举对象.tostring()
返回值:枚举对象名
season autumn = season.autumn;
system.out.println(autumn.tostring());//autumn
values
语法:枚举类名.values()
返回值:所有枚举对象的数组
season[] values = season.values();
system.out.println(arrays.tostring(values));//[spring, summer, autumn, winter]
valueof
语法:枚举类名.valueof("枚举对象名")
返回值:对应的枚举对象
season spring = season.valueof("spring");
system.out.println(spring);//spring
枚举类实现接口
前言:枚举类实现接口可以让枚举类的每个枚举对象都实现接口
接口
public interface testinterface {
void show();
}
枚举类
public enum people implements testinterface {
man{
@override
public void show() {
system.out.println("男人");
}
},
woman{
@override
public void show() {
system.out.println("女人");
}
};
}
测试类
public static void main(string[] args) {
people man = people.man;
man.show();//男人
people woman = people.woman;
woman.show();//女人
}