I. INTRODUCTION
Regression testing is a well-known and commonly used technique that allows developers to make sure their changes don't break the existing logic. To simplify the process of writing tests, we are developing an automatic test generator named UtBot, which produces tests for a given Java program. It uses the program's control flow graph to collect constraints for each possible execution path and tries to cover them with test cases. As we can see from the results of the SBST 2021 tool competition [3], UtBot gives the best coverage and mutation score of all symbolic (and concolic) engines that have participated in the contest.
II.  UTBOT DESCRIPTION
UtBot is a symbolic execution based test generation tool. It automatically produces a set of JUnit tests for a given class or its methods. To do that, the tool requires a Java classpath with all compiled dependencies. UtBot provides an IntelliJ plugin along with a command-line interface. Table I contains the main information about the generator.
III.  IMPLEMENTATION DETAILS
Since UtBot has a symbolic execution engine at its core, it has to analyze multiple execution paths extracted from the program's bytecode. We use Jimple [2] provided by Soot to get a more simple representation of bytecode significantly decreasing the number of instructions. Having obtained a control flow graph (CFG) from the bytecode, we use it to get all the possible execution paths. For each of them, we build a set of constraints that are used by z3 (SMT-solver by Microsoft
[1]) to determine if our path conditions are satisfiable. If they are, we can construct input values from the found model and create a test case that covers the desired branch of the program. A few words about our memory and type systems. We heavily rely on the array and bit-vectors theories to repre- sent symbolic memory. Every Java object in our program is represented by its address and type. Class fields are stored in z3 arrays that contain either addresses or values of objects' fields depending on whether a field is a reference value or not. It allows us to process cases where some objects are equal by reference (so-called memory aliasing). All objects
are represented in the form of constraints on the cells of arrays of symbolic memory corresponding to their fields. Those constraints are stored in the SMT-solver. The type system also uses the described symbolic memory. We strive to cover only reachable instructions of the source code. That is why we have to run our tests to make sure we have generated test cases with valid assertions. Due to a similar reason, we have decided not to use mocks. Tests that employ mocking may potentially cover unreachable code, which would increase code coverage but does not make any sense in terms of software testing.
IV.  BENCHMARK RESULTS
Table II demonstrates the results of UtBot achieved on the competition's benchmarks [3] for each of the given time bud- gets. The produced coverage values vary for different classes. In some cases, coverage reaches the level of 80 – 100%. In other cases, the results are lower. In the following sections, we describe the issues that could lead to the low coverage values for some of the classes.
A. Time limitations
An important factor is the limitations imposed by the time budgets. The symbolic execution technique is inherently time- consuming and that is why in many cases it requires more time in order to achieve better results. To mitigate this problem we have decided to split time budgets into two equal parts. The first part is equally distributed between all methods so that each of them gets some portion of the time. The second part is used to run tests for methods in an arbitrary order.
B. Technical issues
First of all, the results table states that all coverage metrics for the class com.google.common.net .MediaType are zero. However, we could not reproduce this result. In our local launches, we have achieved 25% branch coverage for this class. To calculate coverage we applied the JaCoCo Gradle plugin and used it to automatically generate HTML coverage reports each time our test classes are launched. One other aspect that affects the time consumption of our engine is the requests to the SMT-solver. In some cases they can take significant time, so we have made a temporary decision to use timeouts for each request. Another issue that could have caused some problems in- volves static fields. Although it will be fixed once the engine starts providing the code generator with certain static fields- specific information. There are several other bugs in our tool that we are aware of. Some of them have already been fixed and the rest will also be corrected shortly.
V.  CONCLUSION
Although UtBot has shown the best result of all participants using symbolic execution technique, there is still a vast amount of opportunities to improve our tool in the future. Right now the bottleneck of the engine is its performance and our primary goal is to speed up its work. To do it, we can include concrete execution into our analysis to make our engine concolic.
R EFERENCES
[1] Getting started with z3: A guide. https://rise4fun.com/z3/tutorial/guide. Accessed: 2021-03-10. [2] Arni Einarsson and Janus Dam Nielsen.  A survivor's guide to java program analysis with soot. 2008. [3] Sebastiano Panichella, Alessio Gambi, Fiorella Zampetti, and Vincenzo Riccio.  Sbst tool competition 2021.  International Conference on Software Engineering, Workshops, Madrid, Spain, 2021. ACM, 2021.