Testing Functional Code

In programming, it is essential that developers can ensure that their code works as expected. One way to ensure this is unit testing. However, unit testing and many of the general testing styles are only convenient and simple for basic types of projects. For example, unit tests are great for public libraries made up of classes and functions that can easily be tested. Not only is it easy to test these, but it is simple to understand. You just make objects and call methods and check the results. However, not all code is made up in that fashion.

A clear example of this is a programming language such as my Sea language. In theory, I could take a few weeks and create proper tests for everything involved. However, creating production-level unit tests for a project of this size by yourself is tedious and time consuming, to say the least. One way I find convenient to help test my language is to simply create a sea file with code I want to test the interpretation/transpilation of and then run both the transpiler and interpreter to check the results. Another thing I did was add a debug option to print out the generated tokens, AST, and memory.

This is admittedly janky. There is no standardization for my testing process. Luckily, most of the problems I run into either generate a Python exception, or an obviously incorrect output. That said, maybe that’s only because those kinds of problems are the only ones I find and there are tons of hidden errors that are laying quietly. That overall is one of the best things about Python, and my motivation for Sea. In Python, it is really easy to write thirty lines of code and then run it and have it execute without any errors. This is because the syntax is so simple and readable that its easy to find errors before you even run the code.

Sometimes, I think its alright to not properly commit to testing code. Code that relies more on user input than parameter input (what I’ve called functional code) can be incredibly challenging to properly test. For instance, if I were to properly test Sea, I would need to create sea files that have almost every combination of valid syntax. Not only that, but I’d need combinations of valid and invalid syntax as well to make sure the code finds the errors. The point of testing is to save time and to ensure valid code. In the case of a programming language, I think its easy enough to ensure valid code and in exchange you can save almost half of the total time you’d otherwise need to be spending.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Starting off Clean

I have a noticeable tendency when I’m coding or even when I’m gaming. After a while of making progress, I often reach a point where I’ve learned enough to remake – whatever it is that I made – much better. So, I’ll get to work on modifying what I currently have in an attempt to improve it. This can work sometimes; usually, however, I end up with a lot of complexity laid out in front of me and I become lost in it. Then, I follow my tendency to simply start over.

In my Sea programming language for instance, I started without any real knowledge of how to make a language. I followed a tutorial with pretty bad code and modified it to serve my needs, learning along the way. I’ve recently added all of the combined assignment operators as well as loops. The next step is to add a method of mimicking main memory so I can add functions and proper variable scopes, as well as memory management. So, I want to start off by refactoring the code I currently have. I made decent progress but then I found myself with numerous files open without any new working code. Since I was rewriting basic features anyway, I finally gave in and started rewriting all of the Python code from scratch. The new code can currently be seen in the overhaul branch, until I finish and merge it. (If you’re reading this in the future, that link might not be useful anymore so try this compare link.)

So, I’d like to discuss the benefits and drawbacks of this habit of mine. First off, sometimes, starting off clean just helps manage the complexity of a problem. Being able to go through every file of code and determining which lines are good is incredibly useful and you can find things you otherwise won’t notice. With git and the ability to copy and paste, it takes hardly any time to reincorporate good code. However, I tend to still think of this process as something I ideally shouldn’t do. Maybe it would save me a lot of time to simply refactor what I need to. It’s possible I just need to get better at refactoring. However, it’s also possible that I’m simply new at a lot of this and in the future I’ll write more solid code from the beginning anyway.

I think, at least in this current Sea overhaul, starting off clean has been nothing but positive for me. This is code I’m very new with and having added so many features, I understand it significantly better than when I first wrote it. I think at the end of the day, both refactoring and starting off from the beginning are valid strategies. As we learn, we’ll learn which to use when. If you only need to make a few changes, then just refactor the code you already have. However, when you’re faced with a massive redesign, just take the time to rewrite it. The problem isn’t so much which you choose to do, but rather when you decide to do one over the other.

From the blog CS@Worcester – The Introspective Thinker by David MacDonald and used with permission of the author. All other rights reserved by the author.

Testing with Mockito

During class, we have been doing many testing methods including Junit 5 and for the past two weeks we have been using Mockito, so for today’s blog, I want to focus more on the framework and testing with Mockito. Before we get started let us talk about what is mocking. Mocking is a process of developing the objects that act as the mock or clone of the real objects. In another word, mocking is a technique where mock objects are used instead of real objects. The purpose is to isolate and focus on the code being tested. Mock uses objects such as Fakes, Stubs, and mocks. A fake object has working implementation but takes shortcuts which makes them not suitable for production. Stub object usually does not respond to anything outside that is programmed in for the test. Mocks are objects that are preprogrammed with expectations which form a specification of the call that is called to receive.

Now let us move on to what Mockito is, Mockito is a java based mocking framework that internally uses the Java Reflection API to generate mock objects for a specific interface. Mock objects as I explained previously are used as dummy objects. The main purpose of using the Mockito framework is to simplify the development by using mocking external dependencies and use them in the test code. Few benefits of Mockito include writing beautiful tests with a clean & simple API, it creates mock objects using annotations like for example @Mock, and In Mockito, there is no requirement for writing your mock objects. The first link I have provided gives a lot of detailed examples of Mockito. It has helped me to learn the framework fully. I highly recommend to check it out and follow the example.

https://www.vogella.com/tutorials/Mockito/article.html

https://site.mockito.org/

https://www.javatpoint.com/mockito

From the blog Derin's CS Journey by and used with permission of the author. All other rights reserved by the author.

Object-Oriented Testing

Some of the common methods of testing we know and learned are unit testing, which tests the software at a single unit or class file, and we also have system testing that tests different part of the system. However, as software is becoming more complicated and there are many class files in a software project, one important method of testing that has become useful over the years is object-oriented testing. Normal testing methods won’t be able to be used in these sorts of circumstances because of the different object-oriented features such as inheritance, polymorphism, abstract classes, and other related concepts to it. There are different ways to test the classes and the same methods for testing functions won’t be able to be applied because a single function is completely different than an entire class output.

For object-oriented testing, there are a lot more dependencies that are required compared to normal testing styles. Testing functions are a lot more simpler than testing objects and so more factors need to be taken into account. The first additional testing method for object oriented testing is known as fault based testing. This way of testing tries to come up with test cases that predict any faults that are possible and these test cases are there to solve the errors. The fault based testing doesn’t find all the possible errors and it only tests for the requirements of the client. The next type of testing method is class testing based on method testing and for this one each method is tested similar to unit testing and all the methods are tested for a class one time at the bare minimum. The next type is random testing is for random test cases that is responsible for the operations that are related to behavior of certain categories of the software. The next version of testing for object-oriented testing is partition testing which takes into account inputs and outputs for a certain category and this reduced the total number of test cases. The last contrasting test case is scenario-based testing which takes into account different actions that a user will take and tests for those separate scenarios. Overall, object-oriented testing has similar concepts to conventional testing but there are many other types of testing that are also included that vary from the normal way.

Links:

https://www.geeksforgeeks.org/object-oriented-testing-in-software-testing/

From the blog CS@Worcester – Roller Coaster Coding Journey by fbaig34 and used with permission of the author. All other rights reserved by the author.

Detailed and basic usage of Mockito

 Mockito is a Mock framework for Java single-testing, but it can also be used with other single-testing frameworks in addition to JUnit. Mockito changes the behavior of a class or object, allowing us to focus more on testing the code logic without the effort of constructing the data.

The basic concept

Mocks can be of two types, Class and Partial,so Mockito is called spy. The behavior of changing methods on mock objects is called Stub.

A Mock process is called a Mock Session, and it records all the Stubbing. It consists of three steps:

+———-+ +——+ +——–+
| Mock/Spy | ===> | Stub | ===> | Verify |
+———-+ +——+ +——–+

Class Mock

A Class Mock changes the behavior of a Class so that the object it mocks completely loses its original behavior.

Method returns default values (null, false, 0, etc.) if it is not pegged.

The most basic usage is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
import static org.mockito.Mockito.*;

// use List.class to creat a mock subject --- mockedList

List mockedList = mock(List.class);

//operation of mockedList

mockedList.add("one");
mockedList.clear();

//validation

verify(mockedList).add("one");
verify(mockedList).clear();

Partial Mock(spy)

If we only want to change the behavior of an instance, we need to use spy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List list = new LinkedList();
List spy = spy(list);

// optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

// using the spy calls *real* methods
spy.add("one");
spy.add("two");

// prints "one" - the first element of a list
System.out.println(spy.get(0));

// size() method was stubbed - 100 is printed
System.out.println(spy.size());

// optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

As you can see from the code, the main difference between a Spy and a MockSettings is that the MockSettings for a Spy needs to be passed in a SpiedInstance.

The default Answer to a spy is CALLS_REAL_METHODS, which means that if a method is not stub, it performs its real behavior.

The default Answer to a mock is RETURNS_DEFAULTS. Methods that are not stub return a default value.

source:

https://www.vogella.com/tutorials/Mockito/article.html

https://howtodoinjava.com/mockito/junit-mockito-example/

From the blog haorusong by Unknown and used with permission of the author. All other rights reserved by the author.

Detailed and basic usage of Mockito

 Mockito is a Mock framework for Java single-testing, but it can also be used with other single-testing frameworks in addition to JUnit. Mockito changes the behavior of a class or object, allowing us to focus more on testing the code logic without the effort of constructing the data.

The basic concept

Mocks can be of two types, Class and Partial,so Mockito is called spy. The behavior of changing methods on mock objects is called Stub.

A Mock process is called a Mock Session, and it records all the Stubbing. It consists of three steps:

+———-+ +——+ +——–+
| Mock/Spy | ===> | Stub | ===> | Verify |
+———-+ +——+ +——–+

Class Mock

A Class Mock changes the behavior of a Class so that the object it mocks completely loses its original behavior.

Method returns default values (null, false, 0, etc.) if it is not pegged.

The most basic usage is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
import static org.mockito.Mockito.*;

// use List.class to creat a mock subject --- mockedList

List mockedList = mock(List.class);

//operation of mockedList

mockedList.add("one");
mockedList.clear();

//validation

verify(mockedList).add("one");
verify(mockedList).clear();

Partial Mock(spy)

If we only want to change the behavior of an instance, we need to use spy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List list = new LinkedList();
List spy = spy(list);

// optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

// using the spy calls *real* methods
spy.add("one");
spy.add("two");

// prints "one" - the first element of a list
System.out.println(spy.get(0));

// size() method was stubbed - 100 is printed
System.out.println(spy.size());

// optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

As you can see from the code, the main difference between a Spy and a MockSettings is that the MockSettings for a Spy needs to be passed in a SpiedInstance.

The default Answer to a spy is CALLS_REAL_METHODS, which means that if a method is not stub, it performs its real behavior.

The default Answer to a mock is RETURNS_DEFAULTS. Methods that are not stub return a default value.

source:

https://www.vogella.com/tutorials/Mockito/article.html

https://howtodoinjava.com/mockito/junit-mockito-example/

From the blog haorusong by Unknown and used with permission of the author. All other rights reserved by the author.

Detailed and basic usage of Mockito

 Mockito is a Mock framework for Java single-testing, but it can also be used with other single-testing frameworks in addition to JUnit. Mockito changes the behavior of a class or object, allowing us to focus more on testing the code logic without the effort of constructing the data.

The basic concept

Mocks can be of two types, Class and Partial,so Mockito is called spy. The behavior of changing methods on mock objects is called Stub.

A Mock process is called a Mock Session, and it records all the Stubbing. It consists of three steps:

+———-+ +——+ +——–+ | Mock/Spy | ===> | Stub | ===> | Verify | +———-+ +——+ +——–+

Class Mock

A Class Mock changes the behavior of a Class so that the object it mocks completely loses its original behavior.

Method returns default values (null, false, 0, etc.) if it is not pegged.

The most basic usage is as follows:

1
2
3
4
5
6
7
8
9
10
11
12
import static org.mockito.Mockito.*;

// use List.class to creat a mock subject --- mockedList

List mockedList = mock(List.class);

//operation of mockedList

mockedList.add("one");
mockedList.clear();

//validation

verify(mockedList).add("one");
verify(mockedList).clear();

Partial Mock(spy)

If we only want to change the behavior of an instance, we need to use spy:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
List list = new LinkedList();
List spy = spy(list);

// optionally, you can stub out some methods:
when(spy.size()).thenReturn(100);

// using the spy calls *real* methods
spy.add("one");
spy.add("two");

// prints "one" - the first element of a list
System.out.println(spy.get(0));

// size() method was stubbed - 100 is printed
System.out.println(spy.size());

// optionally, you can verify
verify(spy).add("one");
verify(spy).add("two");

As you can see from the code, the main difference between a Spy and a MockSettings is that the MockSettings for a Spy needs to be passed in a SpiedInstance.

The default Answer to a spy is CALLS_REAL_METHODS, which means that if a method is not stub, it performs its real behavior.

The default Answer to a mock is RETURNS_DEFAULTS. Methods that are not stub return a default value.

source:

https://www.vogella.com/tutorials/Mockito/article.html

https://howtodoinjava.com/mockito/junit-mockito-example/

From the blog haorusong by and used with permission of the author. All other rights reserved by the author.

Sprint 2 Retrospective

Links:

https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/reportingsystem/community/-/issues/40

This was for designing how the database would look and the schemas for all the different fields required.

https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/reportingsystem/community/-/issues/30

This was for the implementation part of the reporting database that I designed.

https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/reportingsystem/community/-/issues/26

This was for reviewing css and html using tutorials online.

https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/reportingsystem/community/-/issues/23

I worked on designing the API for some of the backend endpoints by playing around with swagger.

https://gitlab.com/LibreFoodPantry/client-solutions/theas-pantry/reportingsystem/community/-/issues/80

We worked on creating an open api yaml file that will be used in the next part of the sprint.

The thing that worked well in this sprint for our group, the reporting system, was that before we started the sprint we were able to break down more efficiently what everyone’s role would be. For this sprint we added one more person, and they were responsible for their iam system and each of us had our roles. However, this time I was able to work separately on my issues and then meet with them team for issues that are related to the whole team and how we can help each other out. A lot of the database stuff I was working on was related to the backend aspect, so I worked on that with the other teammate who was assigned the backend role.

Some things that didn’t work well was that we had problems with some of the things we were supposed to do with the report. It was unclear in the beginning what aspects would go in the report and which teams would be sending what. So for this sprint there was a lot of meetings to figure out more of the aspects of the report and not as much as being able to implement the features required.

A few changes we could have made as a team for future sprints are to have the meetings with other teams or product owner about the specifics earlier on in the sprint. This way we can focus on creating the different schemas and backend as well as frontend implementations that are required for the overall pantry and not be stuck on the details. With this procedure, we can get more work done and if there is any confusion we can meet and clear it up after we have done some more implementations on our parts.

Changes I can make as an individual to improve the sprint is to figure out all the details of my role first, then start working. There is not point in getting confused on what to do and start working without a clear grasp. This is where I can work with my team more and ask more questions about a certain issue I have. Instead of working independently on all my tasks, I can ask my team for certain things that there are issues on.

Overall, I think the second sprint was really helpful managing confusion with the project and sorting it out to a solution by meeting with the team and others. I think we helped each other out with the details by meeting with other teams and the product owner who had more details about the product we were supposed to make. I think it was a good learning experience and successful sprint and I am looking forward to the next sprint.

From the blog CS@Worcester – Roller Coaster Coding Journey by fbaig34 and used with permission of the author. All other rights reserved by the author.

Software QA Log #5: Learning and Utilizing Mockito

In a previous post I mentioned mocks in passing as one of the techniques used for test doubles. However, in that brief mention, I noted that mocks can be utilized in unit testing without having to create an actual object with actual values to test the behavior of a class. In essence, mocks aren’t too dissimilar to fakes or stubs; mocks are also pre-programmed to follow certain behaviors. However by utilizing mocks , unlike those test double techniques I mentioned in my previous post, programmers can utilize mocking testing frameworks, which can help significantly in automating and conducting unit testing. Though there are multiple mocking frameworks that can be utilized, I will be focusing mostly on Mockito as it is more well-known, however there are multiple other frameworks that may be stronger where Mockito is weak.

First, it is important to understand what a mock object is in order to understand how it can be used with frameworks like Mockito. Mock objects are essentially replicas of actual objects that are to be used in their place during behavior testing. By utilizing interfaces, a mock object can replicate the behavior of an original object without needing to address any other dependencies. Thus, mock testing allows us to test parts of a program without needing to use its resources themselves. One example where we would want to use mocks would be if our program needed to connect to a database and retrieve information. Instead of having to actually access the database and use real data, the mock object adjusts its behavior to accommodate for the specific unit test. In essence, mocks are similar to fakes.

An example of a mock is the following:

Source: https://dzone.com/articles/mockito-pros-cons-and-best

Unlike fakes, mocks can utilize multiple mocking frameworks. One such mocking framework is, as I mentioned earlier, Mockito. Mockito is a widely used JAVA-based mocking framework that can be often used in tandem with JUnit. Unlike JUnit, which is used to test the source code, Mockito uses mock objects to test in place of real objects. Moreover, unlike JUnit, Mockito can help in keeping track of when and how many times a method is being invoked and even verify if a certain method is being called, something that cannot be done right away with JUnit. However, along with the good things that Mockito brings to the table, Mockito has its own weaknesses, namely that it may not mock constructor methods as currently as version 3.x, or it cannot verify methods like toString().

Like with other test double techniques, mocking and Mockito are not the end-all be-all of testing, but some tools that can be utilized to help create and automate reliable tests for software. Depending on the software’s and the programmers’ needs, different frameworks or techniques might be preferable, however mocking and Mockito are among the solutions that one can learn and use.

Sources/Articles referenced:
1) https://www.toptal.com/java/a-guide-to-everyday-mockito
2) https://circleci.com/blog/how-to-test-software-part-i-mocking-stubbing-and-contract-testing/
3) https://www.accenture.com/us-en/blogs/software-engineering-blog/to-mock-or-not-to-mock-is-that-even-a-question
4) https://www.diffblue.com/blog/testing/mocking-best-practices/
5) https://swiftsenpai.com/testing/test-doubles-in-swift/
6) https://github.com/mockito/mockito/wiki/FAQ

From the blog CS@Worcester – CompSci Log by sohoda and used with permission of the author. All other rights reserved by the author.

Path Testing

For the fourth assignment in the Software Quality Assur&Test class we had to create a program graphs and a DD-Path graph. We had worked during class time in different activities that covered this assignment so I would say I really enjoyed working in this assignment. We had to complete three parts each with a different level of difficulty, but I did only basic and intermediate. I learned to understand more of the way how to create the graphs and what you need to place in the graph and what not.

We have given a java code and I have to create the Program Graph for the play () method. In a Graph, we have a set of nodes (a.k.a vertices) and these nodes relate to each other with the help of some edges. The nodes or vertices are used to store data and this data can be used further. To build the graph is easy but complicated at the same time. All the 27 lines of the code are represented with 27 nodes and some of the nodes have more than one line.

A graph is a data structure that consists of the following two components: 
1. A finite set of vertices also called as nodes. 
2. A finite set of ordered pair of the form (u, v) called as edge. In a Connected Graph, from each node, there is a path to all the other nodes i.e., from each node, you can access all the other nodes of the graph. But in a Disconnected Graph, you can’t access all the nodes from a particular node. Our graph is a combined one.

After finishing the graph, I had to Create the DD-Path Graph for the play () method given above and include the table translating from Program Graph nodes (from your graph above), with the corresponding DD-Path node labeled with a letter. The most difficult part is done in the first part so creating the DD-path and the table it didn’t took me a long time to translate it to what was required. Overall, it was fun assignment and I really enjoyed.

From the blog CS@Worcester – Tech, Guaranteed by mshkurti and used with permission of the author. All other rights reserved by the author.