Hello. In this video, I want to show you an alternative way of writing tests that helps to increase the coverage of the tested domain, and to discover edge cases. In the previous video, we have implemented the following test for the Fibonacci method. Is it enough to check five cases to conclude that the implementation is correct? Writing each test example takes a bit of time. Generally, program domains are huge and it would be impossible to write test cases manually for the whole domain space. You can maybe make the effort of writing test for the of use edge cases, but you would still miss a lot of cases. Another approach is to generate random input data. However, this changes the way you write tests. Indeed, how can you specify the expected result of coding a program with data that, that you don't know. You can only specify general properties that must be correct for all possible inputs or a well delimited subset. In the case of the Fibonacci method, an example of property that we want to check is this Identity. The fact that any Fibonacci number is the sum of the two previous Fibonacci numbers, which is the definition of Fibonacci suite. In this video, we will use the library ScalaCheck to write property-based tests. It integrates with MUnit so that you only need to add the following dependency to you build.sbt file, add a library dependency and MUnit scalaCheck artifact. You keep the same test remark definition as we shown in unit testing video. A test suite containing properties is a class that extends MUnit that ScalaCheckSuite like here. You define properties by calling the method property in the body of the class, like the method test that we have seen in the previous video. The method property takes as the first parameter, the name of the property, and as a second parameter a block that contains the definition of the property tick. Use the method forAll to define the content of the property. The method forAll takes as a parameter a function that receives an arbitrary value here, n of type Int, and that returns a Boolean result. Here the function takes as parameter an arbitrary input to data of type Int and returns a Boolean value, which is the result of evaluating the property. In this example, we check that Fibonacci of n is equal to Fibonacci of n minus one plus Fibonacci of n minus two. You can run property-based tastes like usual test suites by clicking on the test button just above the class definition. Here I've started the test, it takes a bit of time to execute. Alternatively, I could also have invoked the task test in SBT. When Scala checks this property here, it generates several random Int values and evaluate for every value whether the expression here is true or not. We get this test report here that tells us that the property Fibonacci, this one, failed after four passed tests. ScalaChecked, generated four random values for which the property was true and the fifth one falsified the test. The value that falsified the test is given here, it's one. This means that Fibonacci of one was not equal to Fibonacci of one minus one plus Fibonacci of one minus two. Set otherwise, Fibonacci of one was not equal to Fibonacci of zero plus Fibonacci of minus minus. The problem here is that there is no zero element or minus one element in the Fibonacci sequence. The first element of the Fibonacci sequence has index one. Indices below one are just invalid, we should exclude such input values from our tests. Or we could narrow the input type of the Fibonacci method so that instead of taking an Int here, it could take a posInt whose value would be guaranteed to be always greater than zero. We can control how the input data is generated by explicitly supplying a generator. I define a generator named fibonacciDomain of type Gen of Int because it generates values of type Int. The generator chooses an arbitrary value between three and Int, that max value. I choose three here because in my tests I'm writing n minus two. I know that if the lower bound of my generator is three, the lowest possible value I can get here will be one. I supply my custom generator as a first argument of the fall method so that the property will use these generator instead of the default int generator. Now, if I run again the test, let's see what happens. After a couple of minutes, the test should completes and the test passed. Another property of Fibonacci numbers is that they are all positive numbers, I can write property for that. Every result of the Fibonacci function applied to an arbitrary number generated by the Fibonacci domain must return a value greater or equal to zero, that's what this property says. Here I'm going to change the definition of the domain to include the value one, because that's really what the domain of the Fibonacci sequence is. What I will do is that in the first property, I will exclude the values one and two because I want these property to be applied only two values starting from three. Good, let's run the test two again. Again, after a couple of minutes the test two execution finished. Here we see that the first properties still passes, but the second property, it didn't pass. Let's see the output, it says that with this argument, the result of calling Fibonacci, was not a positive number. What's going on here? We see that running the tests reveals that our Fibonacci method sometimes returns negative numbers. What happens is that arithmetic, an Int value on the Java virtual machine is different from arithmetic on natural numbers. In particular, on the JVM, adding two positive numbers to positive Int values can result in a negative result. In the case of the Fibonacci sequence, the numbers almost double each time, meaning that the 30-second Fibonacci number is close to two to the power of 32, which cannot be represented on an int value. In practice, we can use a worksheet to find the edge cases. We see that Fibonacci of 32 returns a positive value. We can continue like that. Fibonacci of 47 still returns a positive value, but Fibonacci of 48 now returns a negative value. It seems that our method is correct only up to the 47th Fibonacci number. What I do here is that I update the generator to only cover the domain that is currently supported by my program. Now I can run again the test and it will be faster to finish. Alternatively, we could have used another data type than int, like big int to not have the problem of wrong arithmetic. Now that all the tests pass, let's go back to the slide. Good properties may be hard to find or formulate. You should look for invariance like also Fibonacci numbers up positive and identities like Fibonacci of n to be equal to Fibonacci of n minus one plus Fibonacci of n minus two. You can learn more about this in the talk, much ado about testing by Nikola Rinaudo, which you can find online. To summarize, property-based testing makes it easier to increase the coverage of the tested domain and helps to find edge cases. In our case, we were able to find the limit of our implementation of Fibonacci. However, good properties can be hard to find. Be careful to not re-implement the system under test.