Java smallholder cultivation record day 24

Posted by rich1983 on Fri, 28 Jan 2022 21:32:55 +0100

day24

Chapter I Junit unit test

1.1 what is unit testing?

In computer programming, Unit Testing (English: Unit Testing), also known as module testing, is a test to verify the correctness of program modules (the smallest unit of software design). The program unit is the smallest testable part of the application. Simply put, it is to test whether the stability of the data meets the expectations of the program.

1.2 black box test and white box test

Black box test

Black box test is also called function test. It tests to verify whether the program can be used normally. In the process of testing, we regard the program as a box that cannot be opened. We can't see anything in black, and we don't know how to write the internal code. That is to say, Input parameters for the program without considering any internal structure and performance, and then check whether the program Output is within the normal range. Usually, we need more tests at this time to draw a conclusion.

White box test

White box test is also called structure test. Here, the white box test is different from the black box test. In the test process, we can see the program as a visible white transparent box. We know the code and structure inside the box. When we use white box testing, testers must check the internal structure of the program, start from checking the logic of the program, check the Input parameters step by step, check the running process and Output results of the program, and finally get the test data. This is why the "white box test" is called exhaustive path test. Again, it is because we know the internal structure and code of the program, so as to check whether all structures are correct and expected values.

1.4 transmission of unit test ideas

Here, we forget about unit testing and test the data in the way we usually test ourselves to see what its shortcomings are. First, I'll create a calculator class in which I can create two arithmetic methods for our simulation test.

package cn.itcast.junit;
/*
    Calculator class
 */
public class Calculator {
    public int add (int a, int b){
        return a + b;
    }
    public int sub (int a, int b){
        return a - b;
    }
}

Then we write test classes, create objects, and test addition first.

package cn.itcast.junit;

public class CalculatorTest {
    public static void main(String[] args) {
        Calculator c = new Calculator();
        int result = c.add(1, 2);
        System.out.println(result);
    }   
}

After the test, we check that the result is correct, and then proceed to the next test. Because we have two pieces of data to test, we usually need to annotate the tested data after testing one piece of data, and then carry out the next test. As follows:

package cn.itcast.junit;

public class CalculatorTest {
    public static void main(String[] args) {
        Calculator c = new Calculator();
        int result1 = c.sub(1, 2);
        System.out.println(result1);
    }   
}

1.5 coding specification of unit test

There are several coding specifications for unit testing. Let's take a small notebook and remember it!

  • Class name: defines the Test class. The class name is composed of the tested class name Test. For example: CalculatorTest
  • Package name: the defined test class needs to be placed in XXX xxx. xxx. Test package. For example: package CN itcast. test;
  • Method name: the method name of a test method can be defined in two ways: Test Method and test method. For example: testAdd and add
  • Return value: because our method is only tested in the class and can run independently, we don't need to process any return value, so we use void here. For example: public void add();
  • Parameter list: because our method is used for testing, it is not necessary to pass in the parameter list. We can pass in the required parameters when testing. Therefore, the parameter list is empty. For example: public void add();
  • @Test note: the test needs to be run to complete. If we have only one main method, it is obvious that we need to comment out the tested methods structurally. To solve this problem, we need to add @ test annotation above the test method to complete the test. As long as it is a method with this annotation, we can run this method alone to complete the test.
  • @Test annotation jar packages Junit4 and 5: @ test annotation can only be used after we import the jar package. There are two jar packages: junit-4.13-rc-2 and hamcrest-core-1.3. Here I use Junit4, unit test and Junit5. I don't understand the version differences. The main reason is that you can complete the test!
  • IDEA quick import Junit4, 5: little friends using IDEA, your gospel is coming. We can first create Test classes and methods, and then add @ Test annotation above the Test method. At this time, the @ Test annotation displayed in the IDEA is red. At this time, we use Alt + Enter to open the list of imported Junit unit tests, and then select Junit4 or Junit5 to confirm that the import is successful! At this time, if you check the annotation again, it won't be red!

1.6 @Test and Assert assertion steps

assert methods describe
assertNull(java.lang.Object object)Check whether the object is empty
assertNotNull(java.lang.Object object)Check whether the object is not empty
assertEquals(long expected, long actual)Check whether the values of long type are equal
assertEquals(double expected, double actual, double delta)Checks whether the double values of the specified precision are equal
assertFalse(boolean condition)Check whether the condition is false
assertTrue(boolean condition)Check whether the condition is true
assertSame(java.lang.Object expected, java.lang.Object actual)Check whether two object references refer to the same object (that is, whether the objects are equal)
assertNotSame(java.lang.Object unexpected, java.lang.Object actual)Check whether the two object references do not refer to the unified object (i.e. the objects are unequal)

First, let's write the test code according to Junit unit test specification, as follows:

Then we will find that there is a small green triangle on the left of each method to be tested, which is used for unit test running. That is, we can run only one method to test. Now let's run the add() method. The result is as follows:

At this time, we found that the console was green and printed out the results, which showed that there was no problem with our program. What would happen if I added an arithmetic exception? As follows:

Here we will find that the console turns red and gives error messages. This proves that there is a problem after the test of our program. This is only the relationship between program correctness and failure.
What if we need an expectation? So the test result is not the expected value I want, and the program is still green. What if it proves that the program is OK? Some small partners will say that we have checked the information of the print console. If the print result is not the expected value, it indicates that there is a problem with the program and needs to be modified. Yes, there's nothing wrong with saying that. However, in our development, what if you see green because of your negligence or fatigue and feel that there is no problem with the program? Therefore, in the face of this problem, we try not to print the expected value during unit testing. We need to pay attention to the observation that green and red are better. It can intuitively reflect whether the accuracy of the program and achieve the expected value.
At this time, we need to introduce a static method of the object to assert whether it is the expected value.

Assert.assertEquals(Expected value, result);

At this time, we found that the method of Assert period can Assert both array and ordinary data types. So let's use it to Assert the expected value. As follows:

Note: when we use assertions, try not to assert double objects. For double precision numbers, it is absolutely necessary to use increment for comparison to avoid the problem of floating-point rounding. If you use the 3-parameter version of assertEquals with the double parameter.

assertEquals(double expected, double actual, double delta);

In this way, double will be automatically unboxed and everything will be normal, so that the test result will not fail. Otherwise, if the double type is asserted with two parameters, the following error messages will be reported:

1.7 @Before and @ After annotation

In the above, will you find some repetitive operations? For example, each of our methods needs to go to the new object. Some smart friends will say that we can mention it in the class at the same level as the method. Yes, this treatment is also a positive solution.
However, in Junit unit test, we have an @ Before annotation, which is used as an application for resources. That is, the method modified by @ Before annotation will be automatically executed Before testing the method. Therefore, we can define an init method to initialize the process of creating objects. This is the function of @ Before annotation!
Some application scenarios, such as read and write operations of IO streams. If we want to test this code, we need a process of closing the flow. By closing the flow, we use the finally block to ensure the closing operation of the last flow. At this time, we have an @ After annotation in Junit unit test, which is used to close resources. That is, the method modified by the @ After annotation will be executed After the test method. Therefore, when we need to ensure the final closure and destruction of resources, we can define a close method to close or destroy resources. This is the function of @ After annotation!

Note: @ Before and @ After annotations can still ensure the initialization, closing and destruction of data when the program reports an error. The two methods are still implemented. This is a bit like the initial stage and destruction stage of our tomact server. Their execution is not affected.

import cn.itcast.junit.Calculator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;


public class CalculatorTest {
    /*
        Initialization method:
        For resource application, all test methods must be executed before execution
     */
    @Before
    public void init(){
        System.out.println("init......");
    }
    /*
        How to release resources:
        After all test methods are executed, the method will be executed automatically
     */
    @After
    public void close(){
        System.out.println("close......");
    }
    /*
        Test add method
     */
    @Test
    public void testAdd(){
        //System.out.println("I was executed!");
        //1. Create calculator object
        Calculator c = new Calculator();
        //2. Call the add method
        int result = c.add(1, 2);
        System.out.println("testAdd......");
        //3. I assert the validity of this result
        Assert.assertEquals(3, result);
    }
}

Chapter II reflection

The soul of frame design: Reflection

  • Framework: semi-finished software. Software development can be carried out on the basis of the framework to simplify coding
  • Reflection: encapsulating the components of a class into other objects is the reflection mechanism
    • Benefits:
      1. You can manipulate these objects while the program is running.
      2. It can decouple and improve the scalability of the program.

2.1 method of obtaining Class object:

package cn.itcast.domain;

public class Person {
    private String name;
    private int age;
    public String a;
    protected String b;
    String c;
    private String d;

    public Person() {
    }

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", a='" + a + '\'' +
                ", b='" + b + '\'' +
                ", c='" + c + '\'' +
                ", d='" + d + '\'' +
                '}';
    }
}
  1. Class.forName("full class name"): load bytecode file into memory and return class object
    *It is mostly used for configuration files, and the class name is defined in the configuration file. Read files and load classes
  2. Class name Class: get the attribute class of generic class name
    *It is used to transfer parameters
  3. Object GetClass (): the getClass () method is defined in the object class. Returns the runtime class of this object.
    *Method for obtaining bytecode of multi object
import cn.itcast.domain.Person;

public class ReflectDemo01 {
    /*
        How to get Class object:
            1. Class.forName("Full Class name "): load bytecode file into memory and return Class object
            2. Class name Class: get the attribute class of generic class name
            3. Object GetClass (): the getClass () method is defined in the object class. Returns the runtime class of this object.
     */
    public static void main(String[] args) throws ClassNotFoundException {

        //1. Class.forName("full class name"): load bytecode file into memory and return class object
        Class<?> cls1 = Class.forName("cn.itcast.domain.Person");
        System.out.println(cls1);
        //2. Class name Class: get the attribute class of generic class name
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3. Object GetClass (): the getClass () method is defined in the object class. Returns the runtime class of this object.
        Person p = new Person();
        Class<? extends Person> cls3 = p.getClass();
        System.out.println(cls3);

        //==Compare three objects
        System.out.println(cls1 == cls2);//true
        System.out.println(cls2 == cls3);//true
    }
}
  • Conclusion:
    The same bytecode file (*. class) will only be loaded once during a program run, and the class object obtained by either method is the same.

2.2 Class object function:

Get function:

Get member variables

  • Field[] getFields(); Returns all accessible public field class objects that contain an array field object that reflects the class or interface represented by it.
  • Field getField(String name); Returns a field object that reflects the specified public member field class object of the class or interface represented by this.
  • Field getDeclaredField(String name); Returns a field object that reflects the specified declared field class object of the class or interface represented by this.
  • Field[] getDeclaredFields(); The returned array field object reflects all field class objects declared by the class or interface represented by this.
    Field: member variable
    Operation:
  1. Set value
  • void set(Object obj, Object value); Sets the Field represented by this Field object on the specified object parameter to the specified new value.
  1. Get value
  • Object get(Object obj); Returns the value of the Field represented by the Field, Field, on the specified object.
  1. Ignore security checks for access modifier
  • void setAccessible(boolean flag)
    A value of true indicates that the reflective object should ignore Java language access checks (such as private) when used. Violent reflex
    A value of false indicates that the reflected object should enforce Java language access checks.
import cn.itcast.domain.Person;

import java.lang.reflect.Field;

public class ReflectDemo02 {
    public static void main(String[] args) throws Exception {
        //1. Get the Class object of Person
        Class personClass = Person.class;
        /*

         */
        //1.Field[] getFields() gets the member variables of all public modifiers
        Field[] fields = personClass.getFields();
        for (Field field : fields) {
            System.out.println(field);//public java.lang.String cn.itcast.domain.Person.a
        }

        System.out.println("======================");

        Field a = personClass.getField("a");
        //Gets the value of the member variable a
        Person p = new Person();
        Object value = a.get(p);
        System.out.println(value);//null
        //Set the value of a
        a.set(p,"Zhang San");
        System.out.println(p);

        System.out.println("======================");

        //Field [] getdeclaraedfields(): get all member variables, regardless of modifiers
        Field[] declaredFields = personClass.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }

        System.out.println("======================");

        Field d = personClass.getDeclaredField("d");
        //Ignore security checks for access modifier
        d.setAccessible(true);//Violent reflex
        Object value2 = d.get(p);
        System.out.println(value2);//null
    }
}

Get constructors

  • Constructor<T> getConstructor(Class<?>... parameterTypes); Returns a constructor object that reflects the specified public class function of the class represented by the constructor object.
  • Constructor<?> [] getConstructors(); Returns all public constructor class objects that contain an array constructor object that reflects the class represented by it.
  • Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes); Returns a constructor object that reflects the specified class function of the class or interface represented by the constructor object.
  • Constructor<?> [] getDeclaredConstructors(); Returns an array class that reflects all constructor objects declared by the class represented by the constructor object.
    Constructor: construction method
    Operation:
  1. create object
  • T newInstance(Object... initargs); Use the Constructor represented by this Constructor object to create and initialize a new instance of the Constructor's declaration class with the specified initialization parameters.

If you use the null parameter construction method to create an object, the operation can be simplified by using the
T newInstance() creates a new instance of the class represented by such an object.

import cn.itcast.domain.Person;

import java.lang.reflect.Constructor;

public class ReflectDemo03 {
    public static void main(String[] args) throws Exception {
        //1. Get the Class object of Person
        Class personClass = Person.class;

        //public Constructor<T> getConstructor(Class<?>... parameterTypes)... Is a variable parameter
        //Class<?>...  Parametertypes is the parameter list of the constructor
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        System.out.println(constructor);
        //create object
        Object person = constructor.newInstance("Zhang San", 23);
        System.out.println(person);

        System.out.println("=======================");
        Constructor constructor1 = personClass.getConstructor();
        System.out.println(constructor1);
        //create object
        Object person1 = constructor1.newInstance();
        System.out.println(person1);

        Object o = personClass.newInstance();
        System.out.println(o);
    }
}

Get member methods

  • Method getDeclaredMethod(String name, Class<?>... parameterTypes); Returns a method object that reflects the method class object of the specified declaration of the class or interface represented by this.
  • Method[] getDeclaredMethods(); Returns all declared methods of the class or interface reflected by an array method object, which represents the class object, including public, protected, default (package) access and private methods, but excluding inherited methods.
  • Method getMethod(String name, Class<?>... parameterTypes); Returns a method object that reflects the specified public member method class object of the class or interface represented by this.
  • Method[] getMethods(); Returns all public method class objects containing an array method object that reflects the class or interface represented thereby, including those declarations inherited from the class or interface and those inherited from the superclass and superinterface.
    Method: Method Object
    Operation:
  1. Execution method:
  • Object invoke(Object obj, Object... args); Calls the underlying method represented by this method object on the method object with the specified parameters.
  1. Get method name
  • String getName(); Returns the name of the method represented by this method object as a string.
import cn.itcast.domain.Person;

import java.lang.reflect.Method;

public class ReflectDemo04 {
    public static void main(String[] args) throws Exception {
        //1. Get the Class object of Person
        Class personClass = Person.class;

        //Method getMethod(String name, Class<?>... parameterTypes);
        //Name: indicates the name of the method
        //Class<?>...  Parametertypes: represents the parameter list of the specified method
        Method eat = personClass.getMethod("eat");
        System.out.println(eat);
        Person p = new Person();
        //Execution method
        eat.invoke(p);

        Method eat1 = personClass.getMethod("eat", String.class);
        eat1.invoke(p, "having dinner");
        System.out.println("=======================");

        //Get the methods of all public modifiers
        Method[] methods = personClass.getMethods();
        for (Method method : methods) {
            System.out.println(method);
            String name = method.getName();
            System.out.println(name);
        }
        System.out.println("========================");

        String name = personClass.getName();
        System.out.println(name);//cn.itcast.domain.Person

    }
}

Get class name

  • String getName(); Returns the name of the entity (class, interface, array class, primitive type or blank) represented by the class object as a string.

2.3 cases

Requirements: write a "framework" that can help us create objects of any class and execute any method

Steps:

  1. Define the full class name of the object to be created and the method to be executed in the configuration file
  2. Load read configuration file in program
  3. Use reflection technology to load class files into memory
  4. create object
  5. Execution method

realization:

  1. configuration file
className = cn.itcast.domain.Student
methodName = sleep
  1. reflex
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;

public class ReflectTest {
    public static void main(String[] args) throws Exception {
        //You can create objects of any class and execute any method
        /*
            Premise: no code of this class can be changed. You can create objects of any class and execute any method
         */
        //1. Load configuration file
        //1.1 create Properties object
        Properties pro = new Properties();
        //1.2 load the configuration file and convert it into a collection
        //1.2.1 get the configuration file under the class directory (the configuration file under the src directory)
        ClassLoader classLoader = ReflectTest.class.getClassLoader();//Get load object
        InputStream is = classLoader.getResourceAsStream("pro.properties");
        pro.load(is);

        //2. Get the data defined in the configuration file
        String className = pro.getProperty("className");
        String methodName = pro.getProperty("methodName");

        //3. Load this class into memory
        Class aClass = Class.forName(className);

        //4. Create object
        Object o = aClass.newInstance();

        //5. Get method object
        Method method = aClass.getMethod(methodName);

        //6. Implementation method
        method.invoke(o);

    }
}

Chapter III notes

3.1 built in annotation

Java Annotation

3.2 user defined annotation

  • Format:

      Meta annotation
      public @interface Annotation name {
      	Attribute list;
      }
    

essence

Annotation is essentially an interface, which inherits the annotation interface by default

public interface MyAnno extends java.lang.annotation.Annotation {}

Properties: abstract methods in interfaces
requirement:

  1. The return value type of the property
    • Basic data type
    • String
    • enumeration
    • annotation
    • Arrays of the above types
  2. The attribute is defined, and it needs to be assigned a value when it is used
    • If you use the default keyword to initialize the default value of the attribute when defining the attribute, you can not assign the attribute when using annotation.
    • If only one attribute needs to be assigned and the name of the attribute is value, value can be omitted and the value can be defined directly
    • When assigning an array value, the value is wrapped with 0. Omit if there is only one value in the array

Meta annotation

Annotation used to describe the annotation

  • @Retention - identifies how the annotation is saved, whether it is only in the code, incorporated into the class file, or can be accessed through reflection at run time.
  • @Documented - marks whether these annotations are included in the user document.
  • @Target - marks which Java member this annotation should be.
  • @Inherited - marks the annotation class to which the annotation is inherited (the default annotation does not inherit from any subclasses)
    Use (parse) annotation in the program: get the attribute value defined in the annotation
  1. Get the object of the location defined by the annotation (class,Method,Field)
  2. Gets the specified annotation
    getAnnotation(Class)
//In fact, a subclass implementation object of the annotation interface is generated in memory
        /*
        public class ProImpl implements Pro{
            public String className(){
                return "cn.itcast.annotation.Demo1";
            }
            public string methodName(){
                return "show" ;
            }
        }
  1. Call the abstract method in the annotation to obtain the configured property value

3.3 cases

package cn.itcast.annotation.demo;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Check {
}
package cn.itcast.annotation.demo;

public class Calculator {

    //addition
    @Check
    public void add() {
        System.out.println("1 +0 =" + (1 + 0));
    }

    //subtraction
    @Check
    public void sub() {
        System.out.println("1 -0 =" + (1 - 0));
    }

    //multiplication
    @Check
    public void mul() {
        System.out.println("1 * =" + (1 * 0));
    }

    //division
    @Check
    public void div() {
        System.out.println("1 / e =" + (1 / 0));
    }

    public void show() {
        System.out.println("Never bug...");
    }
}
package cn.itcast.annotation.demo;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;

/*
    Simple test framework
    When the main method is executed, it will automatically execute all the detected methods (Methods annotated with Check), judge whether there are exceptions in the method and record them in the file
 */
public class TestCheck {
    public static void main(String[] args) throws IOException {
        //1. Create calculator object
        Calculator c = new Calculator();
        //2. Get bytecode file object
        Class cls = c.getClass();
        //3 get all methods
        Method[] methods = cls.getMethods();

        int number = 0;//Number of exceptions
        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        for (Method method : methods) {
            //4. Judge whether there is Check annotation on the method
            if (method.isAnnotationPresent(Check.class)){
                //5. Yes, implementation
                try{
                    method.invoke(c);
                }catch (Exception e){
                    //6. Catch exceptions
                    //Record to file
                    number++;
                    bw.write(method + "The method is abnormal");
                    bw.newLine();
                    bw.write("Name of exception" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("Cause of abnormality:" + e.getCause().getClass());
                    bw.newLine();
                    bw.write("------------------------------");
                    bw.newLine();
                }
            }
        }
        bw.write("A total of" + number + "second");
        bw.flush();
        bw.close();
    }
}

Topics: Java unit testing