# Using discrete math in testing

First of all, I would like to say that mathematics helps to put our thoughts in order and effectively develops logical thinking, and these are some of the most necessary qualities of participants in software development. Speaking of testing, it mainly concerns the behavior of the system, which is orthogonal to the structural representation common to software developers. The difference between structural and behavioral representations is that structural focuses on what the software is, and the behavioral view takes into account what the software does.

One of the difficulties of testers is that the basic technical documentation or software development manual is usually written by and for developers, and the main emphasis is on structural rather than behavioral information. Of course, both structural and behavioral parts are very important for testing, as programming errors can be found in each of these parts. That is why we will talk about discrete mathematical methods to show the relationship between the structure of the program and its behavior.

In their daily work, software quality assurance (QA) engineers work with formula operations, function behavior, and data structures. They always monitor and verify the ever-changing state of systems, so they need to have algorithmic and mathematical thinking to understand the logic of software.

If a developer uses a mathematical approach in his work, as a result, all logical operations will be connected with each other, actions will follow a logical chain, and each function will be considered structurally.

Discrete mathematics helps us find the best solution in various situations. For example, you can find the most suitable set of test cases (Test cases), without covering all possible options. Moreover, discrete mathematics helps us visualize the exact piece of software that has been implemented and covered in tests.

Unfortunately, we do not live in an ideal world, and the expected real results of using the software and actual results may vary. So, the main goal of the Quality Assurance Department (QA) is to effectively cover as many test cases as possible.

To show you this concept in more detail, we created the following Venn diagram with an example that we outlined earlier:

The Venn diagram above describes many situations, thereby helping to illustrate and define sets of situations. For example, this can help us see the difference between sets of objects. Discrete mathematics helps analyze and optimize sets of actions that can affect software being developed.

### Set theory

Using the principles of the theory of basic sets, we can create pseudo-code to illustrate all the possible cases for the Next Day application (a program that calculates which day will be next using the entered date):

```
M1={month:month has 30 days}
M2={month:month has 31 days except December}
M3={month:month is February}
M4={month:month is December}
D1={day:1<=day<=28}
D2={day:1<=day<=29}
D3={day:1<=day<=30}
D4={day:1<=day<=31}
Y1={year:year is a leap year}
Y2={year:year is not a leap year}
```

This pseudocode has already been prepared for the development and testing of the application, so testers can also apply all possible test cases based on this data. Using data in this format helps increase development speed and reduces the chance of error.

### Graph theory

Most discrete mathematics is the so-called "graph theory", which studies graphs. Graphs are used to represent the relationship between some objects or data, and a computer network is a suitable example of a graph.

Graphs are also fundamental to the software development process. For example, using a graph, we can decompose complex functions into several smaller parts, which helps us to better understand business logic.

Graphs can be directional and non-directional, which means that we can move from node to node in one direction or in both directions (in the case of a directed graph), or we cannot move from one node to another (if the graph is directed strictly in one direction)

So, let's go back to software testing and imagine that we have a flow of some process (for example, moving a task in some kind of task tracking system); we have a condition for some problem, and we can move it to another stage (oriented graph), or we can reach some point where we can do nothing with the entity (undirected graph). With this approach to visualization, we can easily assemble a set of all possible actions available for this entity:

Let's continue and look at the adjacency matrix, which can be built on the basis of an undirected graph. In the example below, elements of the adjacency matrix indicate whether pairs of vertices are adjacent or not:

Now imagine that the nodes are the conditions of some entities, and if we construct the adjacency matrix for this graph (set of entities), we will see a finite set of actions that we can take. For example, changing the status from node “0” to node “1” is available because they are related to each other. But the entity “0” cannot be changed to stage “2” or “3”, as we can see from our matrix - “zero” is written in the cells. Using this matrix, we can eliminate unnecessary sets of entity steps and reduce the set of test cases.

Another matrix that we can use to collect test cases is the incidence matrix, which shows the relationship between two classes of objects. In the following figure we see an undirected graph and its incidence matrix: “1”, “2”, “3” and “4” are nodes (entities), “e1”, “e2”, “e3” “e4” are the edges of the graph , and the matrix illustrates the entities and actions that we can do with them. With node “1” we can perform actions “e1”, “e2” and “e3”, but the action “e4” is not available for node “1.”. This method is very helpful in creating a set of test cases.

Imagine that the tester received a list of entities and actions that can be performed with these entities. With this matrix, he can reduce the set of test cases. Reducing the number of tests is a very important part of the software testing process. Software testing is highly dependent on reducing the number of test cases, and with this approach, test coverage and avoidance of redundancy are maximized.

The goal of software testers is to cover the product using effective test cases that allow you to test all possible combinations of actions. Testers can succeed with minimal effort using discrete mathematics approaches (algorithms) to find the optimal set of test cases and maximize the effectiveness of the software testing process.

Discrete mathematics also helps us understand how software is actually created, because all software uses algorithms and methods of discrete mathematics and mathematical logic. Therefore, if we understand how this works, we can find errors or problems within the program that cannot be detected by the user.

### Petri nets

Let's look at an example of how the application works on microservice technology using Petri Nets (dynamic graph):

Here we see that the system has an initial state and should receive some signal that is sent from another service (a marker appears). Depending on the result, the following action should be performed. Thus, the Petri net illustrates the dynamics of the entire system. If any problem exists, we can localize the defect faster.

### Neural networks

Artificial neural networks are also based on graph principles. They imitate the processing of information by neurons of the human brain. Each part of the neural system is based on a graph that contains “input” nodes, a “hidden” layer and “output” nodes.

Some data goes to the input layer, and hidden layer algorithms process this data and send the result to the output stage. Thus, a neural network can perform actions based on this data. Neural networks also consist of many similar graphs with different logic, so they can make decisions based on input parameters.

### Millennium Testing

Our final example of using discrete math in testing involves building a software testing process. Currently, there are many methodologies and approaches called “millenium testing”, which were developed long before their actual use, starting in the 2000s, when software development began to develop rapidly.

BDD (Behavior Driven Development) is part of the so-called Millenium Testing, this methodology is an extension of TDD (Test Driven Development). BDD allows testers to establish a closer relationship between the acceptance criteria for a given function and the tests used to test this functionality. BDD can transform structured statements in a natural language into executable tests, thereby introducing more clarity and understanding to the business side and the development side, as they begin to speak one common language. The basic structure of the BDD workflow is also based on a dynamic graph (Petri Net).

As can be seen from this structure, each process is accompanied by a different process, and it cannot move to the next stage until the previous stage is completed. Once again, the principles of discrete mathematics help us understand the process more efficiently.

In conclusion, I would like to once again list the advantages of using discrete mathematics in the software development process:

- Assistance in understanding the business logic of the required functionality
- Simplify the ability to divide complex tasks into simpler ones
- Enabling professionals to conduct effective testing with less effort
- Help in understanding and visualizing the structure of everything we want

The above examples demonstrate how discrete mathematics can be used to effectively increase test performance. Every aspect of discrete mathematics can help developers understand the general software workflow and its principles throughout the software development life cycle.