Automated Contact Center IVR testing

Introduction

I’m a great fan of Contact Center solutions. I work with them every day both as a customer, and as an architect. They have to deliver consistent experience to company’s customers and at the same time hide complex processes that are deployed in the organization. Being first point of contact for the customers, Contact Center solutions has to be built out of systems that are reliable, stable and provide right information at right time. One of the frontend system of typical Contact Center is IVR (Interactive Voice Response). It often delivers Self Service capabilities, helping customers address their needs without waiting for a free agent to handle the call. Its ease of use, consistent behavior and stable functionality is crucial for company’s image. Hence, there is a great need to fully and completely test IVR system and its configuration before first customer wants to use it. As in other IT fields, automatic testing can be used for that purpose as well.

Self Service testing

IVRs must be tested in two aspects: functional and non-functional. Functional testing helps to guarantee that:

    • Self Service features work correctly,
    • There are no dead ends or loops in the IVR tree.

Non-functional tests are mainly about:

    • efficiency,
    • security,
    • consistency.

Most of the time, Self Service tests are conducted manually. That is because there were no simple ways of checking Self Service as a whole. Self Service has its own complex architecture. It consists of telecommunication components and integrates with company’s internal systems. Using typical process of FAT, UAT and integration tests (taken from application development) it is quite easy to automatically test a particular integration point, API or single Self Service function. However, when it comes to combining those functionalities in a voice channel of Contact Center, new challenges appear. E.g.:

    • do prompts play correctly (are they consistent and do they have high quality)?,
    • is IVR behavior deterministic?,
    • does IVR accidentally disconnect calls (e.g. as a result of external company’s system failure in the integration point)?,
    • can a customer easily access particular options in the IVR tree of Self Service?,
    • is moving between options in the IVR tree intuitive and consistent on different levels of Self Service?,
    • what is the maximum amount of traffic that the Self Service handles without performance degradation?

Those questions are valid no matter which technology is used to deliver an IVR. It can be a traditional IVR subsystems (like Genesys GVP, Avaya AVP or Cisco CVP) where whole tree is directly implemented in the form subsystems’ applications. It can also be a voice chatbot solution with a set of rules that uses keywords and context to determine customer intention and reacts accordingly. Moreover, like any other application, Self Services should be regressively tested after each modification. That alone, may take lots of time. It could save many hours of manual work to introduce automatic testing of IVR applications.

IVR testing approach

For automatic IVR testing we need to create an environment that allows to make a phone call to the IVR and during that call, simulate live person behavior. To make a phone call we can use IP connectivity. In today’s world, most of the Contact Center professional systems support VoIP traffic with SIP (Session Initiation Protocol) signalling. Hence, it is enough to create an application that makes VoIP calls and after connection is establish, sends series of DTMF digits. I will show how to use publicly available libraries to create an application performing automated IVR test.

My testing environment consists of:

    • Freeswitch with IVR module activated (by default it is available at number 5000),
    • PC with Eclipse and Java 1.8 installed,
    • jain-sip library attached using maven (https://www.oracle.com/technical-resources/articles/enterprise-architecture/introduction-jain-sip-part1.html)- for SIP stack,
    • jlibrtp library (https://sourceforge.net/projects/jlibrtp/) – for RTP (Real-time Transport Protocol) stack.

I use jain-sip library to create a valid SIP stack. That allows me to create connections in the signaling layer. When, the connection is established, I open audio session (i.e. RTP receiver’s port and separate RTP outgoing stream with silence). In that way I simulate normal callee that doesn’t say anything and just listens to IVR prompts. IVRs often expect calling party to send DTMF digits – e.g. when called needs to choose particular IVR option or enter PIN to authorize. In SIP world there are several ways to send DTMF digits. One of the wildly supported is to use named telephony events (NTE). The method is described in RFC 2833 and makes use of RTP stream. Digits are inserted into the stream as additional packets. Those packets are specially marked according to what has been negotiated during the signalling phase. My application uses NTE and simulates pressing digits by the customer. Digits are send to Freeswitch and the IVR reacts accordingly. Each prompt played by the IVR is saved by the application to a file for further analysis (e.g. using Automatic Speech Recognition systems).

The high level architecture of the application and its interaction with IVR is presented below.

The application code is a bit long to paste it here and I won’t do that. I hope that the description of how the application works and list of libraries allows you to approach the subject on your own.

Summary

I’ve presented basic components of application that automates testing of IVR systems. The application uses VoIP and publicly available libraries for SIP and RTP stacks. Having such application it becomes straightforward to create automatic IVR testing process. That reduces total cost of tests for new features and regression. If you have questions or need help with automatic IVR testing, contact me via Contact form.

Happy coding 🙂

Automating modbus communication

Modbus is well known industry protocol for communication between electronic devices. It is an application layer messaging protocol, positioned at level 7 of the OSI model. Despite that it had been developed in 1979, the protocol is still heavily used by many manufacturers. It proved to be very efficient and useful mainly because its simplicity. Even simple devices and control boards will handle the protocol. It is good to know at least basics of how to use Modbus especially in the era of IoT.

In this post I show how to create a simple Windows application for Modbus IP communication. The same logic as described in this post can be used in frameworks for automatic testing of Modbus devices.

Modbus communication schemes

There are many implementations of the protocol in lower level of ISO/OSI model. Two of them are:

RTU (Serial port based)

Uses master-slave architecture, where clients are connected to the same communication medium as the master. Only master can initiate communication to particular slave. Each slave has its own id. The master uses that id to address the message. The communication (according to the protocol description) should be time based. However, today’s devices mostly work well even without that restriction.

IP (Internet Protocol based)

The communication on the high level is very similar to HTTP. It uses request – response paradigm. The device sends a message over the IP network and synchronously waits for the response (confirmation). I will use that type of communication for building sample application.

Application implementation

First of all we need to implement communication according to the protocol itself. As the post can’t take too much space, I won’t show how to develop the protocol from scratch. Instead I will use modbuslib (https://libmodbus.org/) library. The library is LGPL licensed and implements both IP and RTU communication schemes. That is exactly what we need. If you would also like to use modbuslib in your projects, remember that using LGPL has some consequences.

Preparation

The modbuslib library is available in a form of source files and has to be compiled before we can use it. The compilation process is described on the library’s page and I will not repeat it here. If you find it complicated or have difficulties in compiling it, let me know. I will do my best to help. After the compilation process in Windows environment we get modbuslib.dll. That is a windows dynamic link library with all the required functions that we need for our application.

For that project I will use C language. It has always been the language for low level operations. Hence, I will use it as a good fitter to the subject 🙂 My environment consists of Eclipse for C and GCC compiler. You can of course use another technology (see my another post on how to use native DLLs in Java).

First, we need to create C project using C manged build template in Eclipse. Having that, we need to tell the linker where modbuslib is, so that it can link objects’ description into our application. Those settings can be found in Project properties / C/C++ Build / Settings. Depending on what compiler you use, settings names may differ. I use MinGW with GCC. Remember that you have to configure both correct include path (i.e. path where header files are located) and library path (path where modbuslib.dll is located).

Write the code

Our application will read particular holding register and display its value on the screen.  All necessary functions to accomplish this goal are defined in modbus.h header file.

Initialize Modbus context

modbus_t structure keeps information about the context od modbus connection. We need to properly initialize the structure with the IP address and port of the remote device. In my case, the device that I connect to is available under the IP address 192.168.1.2 and listens on port number 502.

modbus_t *mb;
mb = modbus_new_tcp ("192.168.1.2", 502);
if (mb == NULL) {
    fprintf (stderr, "Unable to create connection context");
    return -1;
}

Connect to remote device

After having the context initialized, we can now try to connect to the device.

if (modbus_connect (mb) == -1) {
    fprintf (stderr, "Unable to connect to the device");
    modbus_free (mb);
    return -1;
}

Read register and display value

As in typical C program, values have to be stored in some structures, that have to be already initialized. In my case I’ve prepared structure named tab_reg that is an array of  unit16_t. If you prepare the code on your own, please remember to clear this array before using it. Having the tab_reg defined, we can use it to read a holding register. I will read register with id = 200.

if (modbus_read_registers (mb, 200, 1, tab_reg) == -1) {
    fprintf (stderr, "Error reading register from device");
} else {
    printf("%d\n", tab_reg[0]);
}

Finally, we have to clean up resources

    modbus_close(mb);
    modbus_free (mb);

And that’s it. We have created the application that reads holding register from Modbus device and displays its value on the screen.

I encourage you to create Modbus communication app on your own. It is really satisfying to see that the software can work together with industry level devices.

Conclusions

Modbus is a powerful protocol that is commonly used in different kind of devices. I have presented how to prepare simple application that allows to automatically read holding register from modbus device. Such applications an be combined in the framework for automatic testing of modbus devices. The ability to automatically test the device can significantly speed up the overall product testing process. Moreover, such process becomes more repeatable and human error are minimized.

If you look for framework for automatic testing Modbus devices with configurable workflows, contact me.

Happy coding.

Invoking an external native DLL from Java application

Introduction

Many functionalities in today’s applications are delivered in a form of libraries. Thanks to that, programmers don’t need to write whole program from scratch.  They can combine different, already prepared parts of compiled code in bigger application instead. That of course shortens time and lowers the effort needed to prepare an application.  Windows operating system delivers lots of functionalities in shared libraries. In this post I show how to access them from Java application.

Short history of libraries

Since first computers appeared on the market, programmers started to think how to simplify their job. Quickly after first programs had been written, it occurred that those programs have some common functionalities. For example all accounting applications perform the same math operations. If one could take those common parts out and put into a new application, that would very much speed up the process of making new programs. The solution to that challenge was to use functions and procedures. Both represent a part of the application that can be reused in another one. The programmer that developed such part can share it to other programmers. They get fully functional and tested code, and they don’t have to create it from scratch. That saves time, effort and money needed to make new software. To ensure that programmer who got function or procedure can use it in a consistent way (predicted by the author) there had to emerge a standard way of describing its attributes. There were defined 4 basic elements of description of a function or procedure:

    • name,
    • list of input parameters,
    • list of output values (for functions),
    • description what the function or procedure does.

Description what the function or procedure does is rather for humans than for computers so they understand when to use which. In effect developers started to treat name, input parameters and return values as basic attributes that are needed to effectively use delivered function (or procedure). It also occurred that there is rarely a need to distribute single function or procedure. It was a common requirement to distribute a set of those. For instance, if one person developed mathematical function (like a sum) and another wants to use it, there is high possibility that the other person also needs another mathematical functions. Hence, the concept of library of functions and procedures has emerged. From that moment, programmers started to distribute fully functional parts of programs grouped in sets called libraries, and others could use those libraries in their applications. There are two ways of using a library in application.

Statically linked libraries

Initial concept was to distribute library in a form of compiled files (object files). Such libraries are called “static link libraries” and need to be linked into the application right after compilation phase. In the effect of linking process, libraries become inseparable part of the application. Library’s compiled code is actually copied directly in the compiled executable. The resulting executable file has all the instruction, both from the developer’s code and libraries, inside itself.

Shared libraries (also called dynamically linked libraries)

Another approach is to prepare application with assumption that required libraries will be available on the computer on witch the application is to be executed. That is how dynamic link libraries work. In spite of being copied into the the application, they are attached during run time. The end user of the application should be aware of that there is a set of libraries that are required by the application. That information usually comes in installation manual (e.g. DirectX or OpenGL for games). The libraries will be attached during application startup by the operating system. To do so, the OS need to know how to read information about functions and procedures delivered by each library. In the next paragraph I show basics of accessing functions in native shared library from Java code. Those libraries also called dynamic linked library and have .dll extension in Windows environment.

Invoking functions from DLL libraries in Java application

In Java there as a library called JNA (Java Native Access – https://github.com/java-native-access/jna) that makes accessing native DLLs quite easy. As it was mentioned earlier, it should be enough to use name, list of input parameters and return value to effectively invoke a function. Let’s see how it works with JNA. We will prepare a simple application that finds window title of running Eclipse IDE. Firstly, we need to import required packets.

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser;
import com.sun.jna.win32.StdCallLibrary;

Then, we need to define an interface that will be a facade to the the DLL. That interface has to extend StdCallLibrary. We don’t have to define all methods in the interface that are available in DLL. In our application we want to read windows titles. For that we have to use two functions delivered by user32.dll:

    • EnumWindows – enumerates over windows created in the system,
    • GetWindowsTextA – getting window title.

In result, the interface may look as follows:

public interface User32 extends StdCallLibrary {

    User32 INSTANCE = (User32) Native.loadLibrary("user32", User32.class);
       
    WinDef.BOOL EnumWindows(WinUser.WNDENUMPROC enumFunc, Pointer arg);
        
    int GetWindowTextA(HWND hWnd, byte[] lpString, int nMaxCount);
}

First field of the interface loads DLL library. Pay attention to the fact that name of the library is provided without extension. Having the User32 interface defined, we can now prepare the main class. We can name it WinApiWrapper.

import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinUser.WNDENUMPROC;

public class WinApiWrapper {

	private final User32 user32;
	
	public WinApiWrapper() {
        	user32 = User32.INSTANCE;
    	}

	public void run () {
		user32.EnumWindows(new WNDENUMPROC() {
	         
	        public boolean callback(HWND hWnd, Pointer arg1) {
	            byte[] windowTitleBuffer = new byte[512];
	            user32.GetWindowTextA(hWnd, windowTitleBuffer, 512);
	            String windowTitle = Native.toString(windowTitleBuffer);

	            if (!"".equals(windowTitle) && windowTitle.contains("Eclipse IDE"))
	            	System.out.println("Found window with title: " + windowTitle + " (" + hWnd + ")");
	            return true;
	         }
	      }, null);
	}
	
	public static void main(String[] args) {
		WinApiWrapper winApi = new WinApiWrapper();
		winApi.run();
	}

}

For the above example to work, both class and the interface have to be defined in the same package. The class constructor sets user32 variable that gives access to methods from the User32 interface. We can then work on those methods in the same way as on any other Java method.

After running the application, the result is as follows:

If you want to practice on your own, one hint from my side. Passing arguments and getting results from methods invoked from DLL libraries may require additional memory management. You have to manage memory associated with variables by yourself (see how the callback in the run method does it). Otherwise, you will get memory run-time errors.

Happy coding.