Category Archives: CS-443

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 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.

Getting Started With Python Unit Testing After Learning JUnit

Christian Shadis

CS-443 Self-Directed Blog Post #5

This past semester I have been spending a lot of time in my QA class working with JUnit 5. I want to be able to take my familiarity with JUnit and apply the same principles with unit testing in Python. I am leaning toward a data-centric career path and Python is widely used for data analytics, so this would be valuable information for me.

This post is not an expert-authored tutorial on Python unit testing because I, myself, am just getting started with it. In this post I will instead give tiny, bite-sized examples of just the basics, translating it from JUnit to Python unittest. I built identical, small classes in Java and Python, and will build tests to go with them. Below are the classes in Java and Python, respectively.

/**
 * Simple class with basic methods, written in Java
 * @author Christian Shadis
 */
public class main {
    public static void main(String[] args){
        int i = 0; // dummy code to keep compiler happy
    }

    public static int addTwoNumbers(int x, int y){
        return x + y;
    }

    public static String toCapital(String str){
        return str.toUpperCase();
    }
}

# Simple class with basic functions, written in Python
# Author: Christian Shadis

class main:
    def add_two_numbers(x, y):
        return x+y

    def to_capital(string):
        return string.upper()

Writing the unit tests in JUnit is simple: we import the JUnit assertions, and the @Test annotation. Then we create the test class, each of the two tests, setup, exercise, and verify just as always.

/**
 * Test Class for main.java
 * @author: Christian Shadis
 */
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

public class maintest {

    @Test
    void testAddTwoNumbers(){
        int result; // setup
        result = main.addTwoNumbers(566, 42); // exercise
        assertEquals(result, 608); // verify
    }

    @Test
    void testToCapital(){
        String result; // setup
        result = main.toCapital("string"); // exercise
        assertEquals(result, "STRING"); // verify
    }
}

Luckily, writing unit tests is just as easy in Python as Java. We import the unittest library and the other class, define the class, and add a Test Case object as the parameter.

import unittest
from main import *

class maintest(unittest.TestCase):
import unittest
from main import *

class maintest(unittest.TestCase):

    def test_add_two_numbers(self):

        pass
    def test_to_capital(self):

        pass

Now we need a test case for each of our two functions, add_two_numbers and to_capital. Python’s unittest objects have very similar assertions as in JUnit. Use assertEqual(x, y) to check that x == y. This is the assertion we will use in this example, but any of the following are commonly used unittest assertions:

  • assertEqual
  • assertNotEqual
  • assertTrue
  • assertFalse
  • assertIs
  • assertIsNot
  • assertIsNone
  • assertIsNotNone
  • assertIn
  • assertNotIn
  • assertIsInstance
  • assertIsNotInstance

assertEqual takes two arguments and, as the name suggests, asserts their equality. See the implementation below:

    def test_add_two_numbers(self):
        result = main.add_two_numbers(33, 44)
        self.assertEqual(result, 77)

    def test_to_capital(self):
        result = main.to_capital("hi")
        self.assertEqual(result, "HI")

Run the tests and you will see them both pass. Below is a screenshot of the tests executing in Python and then in JUnit. As you can see, the Python tests are slightly faster than the Java tests, but not by much. I used IntelliJ IDEA and Pycharm IDE.

I have found the most helpful way to learn testing is to just play around with the unit tests, see what works and what doesn’t, see what causes failures and what those failures look like, and so forth. I would suggest any other beginner QA student to do the same. Playing around with different assertions and looking at the unittest documentation is a great way to learn this library. I hope this post gave you some insight on how to get started with unit testing your Python modules if you have done some work with JUnit in the past.

4/28/2021

Works Cited:
Unittest – unit testing framework¶. (n.d.). Retrieved April 28, 2021, from https://docs.python.org/3/library/unittest.html

From the blog CS@Worcester – Christian Shadis' Blog by ctshadis and used with permission of the author. All other rights reserved by the author.

Software Quality Assurance and Testing Blog Post #5 (Test Automation)

For my fifth and final topic review for Software Quality Assurance and Testing, I decided to go over test automation. I found a lot of good sources on the internet to help me understand what it is. A lot of the testing practices that we have learned about this semester have been manual testing rather than automated testing. This just means that we would write the tests and go through them ourselves rather than let the computer do it by itself. This works really well with testing methods like discovery testing and usability testing. The reason we would use automation testing is because it is much easier to have the computer run tests for us (especially in cases in which we have repetitive testing). We do not want to be wasting our time running repetitive tests over and over again when the computer could do it all much faster and with a lot less effort. Test automation’s main appeal is the speed that comes with it. One would think that we should just use this type of testing all the time, but the reason we do not is because some testing methods have to be done manually. One of the best sources I found was on testim.io, and I will make sure to add the link for that at the bottom of this post. The article is very good because it describes what automation testing is, what its criteria are, what types of tests are classified as automation, and the general process of using this testing method.

https://www.testim.io/blog/what-is-test-automation/

From the blog CS@Worcester – Tim Drevitch CS Blog by timdrevitch and used with permission of the author. All other rights reserved by the author.

Mockito – Using Spies

Seeing as we are continuing our learning with Mockito, specifically going into spies in Mockito, figured it would be worthwhile to do some research into them. I found this article (https://www.baeldung.com/mockito-spy) from Baeldung by Eugen Paraschiv detailing spy usage and complexities which I found very useful. It begins with a description of spies and then goes into examples of usage.

The first example is used on a real object – a list – which a method is then called upon twice, and then Mockito’s verify is called twice with the same method. This allows for “spying” upon an object, hence the name spies. There is then some detail about the @Spy annotation, stubbing a spy, and then the actual differences between a Mock and a Spy. Chiefly, this difference is that a mock uses the Class of a Type, like a “base-bones shell instance,” while a spy “will wrap an existing instance” and can track it in various ways. This is also followed by a blurb about the NotAMockException from Mockito, which wasn’t immediately necessary for my purposes I don’t think.

Overall, I thought this was a great, useful article. It prepped me for continued learning within Mockito and I felt comfortable understanding it. I think I have a good basic understanding of spies and would be ready to begin using them in testing. They’re a good way to analyze object/method behavior and have useful applications for when a project is only partially written. I look forward to using spies in the future. Most of what I’ve learned within the world of Mockito has been super interesting thus far.

From the blog CS@Worcester – Marcos Felipe's CS Blog by mfelipe98 and used with permission of the author. All other rights reserved by the author.