Horstmann Core Java, Ed 11, Vol I CH 9 Collections
Horstmann Core Java, Ed 11, Vol II CH 1 Streams
2. Test quality
So testing is to improve code quality. But is there any quality measure to tests?
Sure there is:
Work test driven, duh. In the standard TDD cycle, you should have your test to be red first. That’s one.
You can break your code and see if the tests make you aware of it. They should show a nice deep red (at least some of them). If they do not, you are working according to the TDD cycle. That’s two.
You can measure the coverage of your tests. Sebipom provides a tool for that called JaCoCo that you can turn on in your IDE or when running form the command line. It shows how much of the business code is executed by your tests. That’s three.
For the lazy ones (aren’t we all) and easily repeatable too: Have you code automatically mutated by some tool. Your tests should find most if not all issues after mutating. The tool provided for this is pit-test
Let’s go through the method one by one.
These you know:
There is no test before there is a requirement.
And there is no business code before a test.
So if a method is not specified, then do not write a test for it, and do not write the method either.
The only reason to have a method is because the specs demand it. And they should state
what the method is supposed to do
in which states of the object the method call is legal
any requirement of the parameters to the method
specification of result, possibly in a set of input-output tests cases.
any exceptions that can be thrown and under what conditions
the state that the object is left after completion of (or return from) the method.
If the user stories are complemented with proper scenarios (which they should to help you write your test), then you can write the tests easily, feature for feature and thereby test-driven develop the business code.
Writing your test first, which makes the business break first.
Always give the IDE a chance to code-complete whatever you try to invoke in your test, because the business code does not yet exist, so that the test is meaningful. A IDE generated
throw new UnsupportedOpretaionException( "this method needs implementation" ) is not very useful,
but returning something of the proper type (for non-void methods) is a better choice.
If you think it is a sly trick to return the correct value
the first time, then you are in bad luck because:
You will have a test that has not been red.
You will have to invent other test cases, to complement the 'correct' one.
So best start with return
null. If your test is already green in that case, choose another
'impossible' value such as
true or a simplest version of the expected result type , such as
"wrong" for Strings.
2.2. Break your code
If you do not, we will force you. We will regularly, but only after a commit, ask you to break some of the business code to see that the tests notice. We will also do something similar in the correction of the performance assessment, that is we will feed your test broken business code and the test code should notice that.
As promised, breaking your code by a program is easy. It is built in by the magic of pit-test.
mvn test org.pitest:pitest-maven:mutationCoverage
You can also use NetBeans ID.
Click on the project. Then the navigator should show the possible maven goals.
Choose pittest mutationCoverage. This will produce an index.html report in target/pit-reports which contains date-time-stamped folders cont. Choose the latest if you have more of those folders.
You can also have NetBeans IDE remember this by going run maven → Goals →, then in the dialog add
test org.pitest:pitest-maven:mutationCoverage and save it as e.g. pit.
This last results in an addition to the nbaction.xml file like this:
<action> <actionName>CUSTOM-pit</actionName> <displayName>pit</displayName> <goals> <goal>test</goal> <goal>org.pitest:pitest-maven:mutationCoverage</goal> </goals> </action>
4. Lesson Demos
Lesson demos in repository: https://www.fontysvenlo.org/svn/2020/prc2m1/svnroot/lessondemos/
5. Exercises week 5
Exercise 1: Simple Stream
Stream starter exercises
In this exercise you work with the simplestream project.
Starting with streams can be a bit confusing. You will have the best experience if you let NetBeans+ the compiler do some of the thinking for you. And then throw in some tricks.
You can consider a pipeline to have two ends: the start, which is the method that typically is called
stream() and the end, which is your terminal operation.
Often you can start coding by adding the terminal operation from the beginning and insert any intermediate operation between the start and this end of the stream.
int studentcount = students.stream() .count();
There will be some example code in the simplestream project in your repository.
We have the following facts on the students.
There are 50 students in total. The number of male students is 16. The youngest student is s Shirleen Simpson, student number 3134539. The female students whose first name starts with an 'A' are
Since you are experimenting with streams, do not bother to write business methods. There are four test methods in total, which you need to implement. Inside such method, writhe stream code and the assertJ assertions. The javadoc above the tests give some extra hints.
Write tests for operations to compute from the given data set:
The total number of students.
The number of male students.
The youngest student with. The stream method to use returns
Optional<Student>. Think of the proper terminal operation.
The list of femail students whose name start with 'A'. Use Collectors.toList() to collect the matching students.
You can either combine two predicates with the proper logical method or concatenate the strings, before you do the test.
Predicate<Student> redHaired s -> s.getHairColor() == HairColor.RED;
In all cases use streams and lambdas.
(1) Add a field to the Student class holding of Map of study-topics to grade:
Exercise 2: CSV to Objects
CSV to Object Stream
Reading students from disc, or any other kind of object for that matter.
In this task you will write a small utility class that will help you to test things and is also useful to load data from files and e.g. put them in the application or mock data source. The use case of this utility class is to read data from files and turn them into real (Java) objects.
The class is a
CSVObjectReader and has one constructor and two
Of course, you start with tests.
To do that, you will find a
student.csv file in the NetBeans-IDE project.
The test should:
For the constructor call use
Factories::createStudentas creator. This is a method reference. See lambda theory if you forgot what that means. From the String
"students.csv", create a Path java.nio.file.Path using the Paths utility class in the same package.
asListmethods take two parameters:
Function<? super String, ? extends T> creatorthat transforms an array of strings into an object of type
Predicate<? super String>called
rowFilterthat ensures that the array is fit for purpose.
Example: the first string in the array of strings contains only digits and is the student number.
asListmethod uses the
streammethod, and collects the stream into a list.
The testing part should do the following:
Collect the resulting stream in a list and assert that
The list is not null.
The list is not empty.
The list has 50 elements.
The list contains a student with the name
"Olympia Oliphant"at index three.
Use the assert that extracting method with a fieldname as parameter. See the assertJ API and doc for examples.
In all the asserts, use a message and make sure you put the arguments to the
assertThatmethod chained in the proper order.
You can use it as is shown in the listing below
Show that it works
To show the use of this class, create a csv file, of take it from an earlier project, and define a type, say student with studentnumber, name, birthdata, and gender.
To top the demonstration off, add a filter function that accepts a list of students, which streams said list and filters out students by some rule, e.g. by gender and or age.
A Helper class called
Factories might be useful in your demo.
Factories in our solution has two methods, one to create a student
from an array of String, as is required by the
and one method to turn object back into csv records. We call the last
studentAsCSVLine. For the remaining few details look at the
class diagram below.
You may want to keep this project and reuse it in other exercises.
Note that the
Student test class is a static inner class in the factories, which is
only available in the test source tree.
To complete the exercise, add a separate Main file that demonstrates the working of your module.
CSVObjectStream<Student> os = new CSVObjectStream( Student.class, Paths.get( "students.csv" ) ); os.stream( Factories::createStudent, r -> r[ 0 ].matches( "\\d+" ) ) .forEach( System.out::println );
Exercise 3: Lambda Library
Within this assignment you will get more familiar with the syntax of lambda expressions,as well as how to apply them. Furthermore you will use the new streams to get some work with collections done in a smart way.
Note: to run the FX application, don’t click "run" in Netbeans. Assuming you are using a sebipom based project, then first enable the fx profile , then right click the project and either
The FX application works out of the box and you should not touch any of the FX parts. You will only work on the library itself.
Your task is to implement the business logic for a library. This library provides some methods to get access to the books and to retrieve several views on that books. A simple swing-GUI which displays the books of the library is given. You can use that to see parts of your implementation in action.
As usually, you will find an NetBeans project for this assignment inserted in you subversion repository. Note that the project will run, but not all functionality is implemented, yet. Proceed in the following steps:
Start working on this assignment by studying the Javadoc which is given. Take especially care of the classes
SearchStrategy, since they will form the requirements you will have to implement.
Implement one of the test cases in the test class
LibraryModelTest. A good starting point is the
Implement the method for which you wrote the test(s) in the previous step.
It may need more tests if a method has more aspects to fulfill. Each aspect could have a different test.
It is quite common to have more test methods per business method.
Repeat the steps 2 and 3 until all functionality is implemented.
Note that this task has a dependence on the previous task cvsobjects, to read a csv file as book objects.
Additional information on lambda expressions and the java 8 features can be found at the following locations:
javadoc of the application. This provides the requirements of all the methods to be tested and implemented. You can derive your test data from the `library.csv} file.
Update The provided test class has two methods called book(int) and books(int …), where the parameter is called id or ids. This could lead to confusion, when you interpret that as the id of the book in the csv file. It is not that number but simply the index in the List of books, so starts at 0, not 1.