Sharing knowledge with other TwinCAT developers using a blog is not only an easy and good way, but it’s also quite fun. After a long day at work, I often find it enjoying to sit down and write a little bit on a new blog post. Quite recently I launched TcUnit – the TwinCAT unit testing framework and even though there now is tons of documentation and example code on the official website, some people prefer to learn by watching a video. For this reason I’ve created a series of four videos that will introduce TwinCAT software developers to test driven development (TDD) and how to do TDD using TcUnit.
I’m very happy to announce the release of TcUnit – an unit testing framework for TwinCAT3. TcUnit is an xUnit type of framework specifically done for Beckhoffs TwinCAT3 development environment. This is another step in the direction of modernizing the software development practices in the world of automation.
Before dwelling into the details, let me tell the background of this project. In 2016 the development of the CorPower wave energy converter (WEC) was in an intensive phase. Software was being finalized, tested and verified for delivery. In a late phase of the project some critical parts of the software needed to be changed. The changes could be isolated to a few function blocks (FB), so in an initial phase the tests simply consisted of exporting those FBs to a separate project and running them locally on the engineering PC. The FBs were changed and executed in the engineering environment, and then online-changing the inputs and seeing whether the expected outputs were given. After doing this for a couple of hours an important question was raised:
Shouldn’t this be automated?
In my earlier posts I’ve written about development of TwinCAT software using test driven development (TDD), by writing unit tests. One of the advantages by adhering to the process of TDD is that you mostly will end up with function blocks (FBs) which have limited but well defined responsibility. Eventually you will however have FBs that are dependent on other function blocks. These could be FBs that are your own, or part of some 3rd party library, for example a Beckhoff library. Further, what if this external FB relies on some other functionality such as external communication using sockets that we have no control of? The external FBs should already be tested, we’re only interested in making sure our unit tests test our code! What do we do? A solution to this is to mock the external functionality and use dependency injection.
We’re finally at the last post of this series! Patiently we’ve written all our tests and done all our code that implements the required functionality and made sure that our code passes all the tests. But in the end of the day, despite all the theory and coding we want our code to run on a real physical device. Now it’s time for the favorite part of every PLC programmer, which is getting down to the hardware and micro controllers! Let’s get to the grand finale, and test our code on a real PLC, IO-Link master and IO-Link slave.
In part five of these series we started the implementation of the function blocks that we previously have done unit tests for. As we have our tests, we could verify that our newly implemented code did what it is supposed to do, and thus we made our code pass the tests. What we’ve got left is to do the implementation for three of the remaining function blocks. Once this is done, we have implemented all the required functionality that we’ve declared that our unit tests require us to.
In the last post of the series of unit testing in TwinCAT we finalized our unit tests, thus creating the acceptance criteria for the expected functionality for our function blocks. Now it’s time to do the actual implementation of the function blocks that we described in part 2 of these series. As we have our unit tests finished, we can anytime during our development run them and check whether the implemented code passes the tests.
In the previous post we defined the general layout of our unit tests, and also did the implementation of the tests for two of the five function block that we’re going to use to verify the functionality of parsing IO-Link events. What we’ve got left is to create test cases for the parsing of the text identity and the timestamp of the diagnostic event. Then we also want to have a few tests that closes the loop and verifies the parsing of a complete diagnosis history message.
In the last post of this series we were looking at a use case for a certain set of functionality, more specifically creating parser function blocks for the handling of IO-Link events. The result was a series of function blocks with defined input and output. In this post we’ll create the unit tests that will use the function blocks that we’ve started doing. Naturally, when defining the tests they will all fail as we don’t have the implementation code ready yet.
In my previous post I explained some of the benefits of using test driven development (TDD) while developing PLC software. This post is the second part of a series of seven, where we will look at a real use case scenario of writing test cases prior to doing the actual implementation. The scenario which I thought would be good for this is by creating a parser for IO-Link events. Shortly, IO-Link is a standardized point-to-point serial communication protocol used to communicate with sensors and/or actuators. It is not a fieldbus, but only takes care of the communication to the end device. As it’s a fully digital protocol that on top of process data also supports services such as events and parameterization, it’s standing well prepared for the Industry 4.0 thinking. One of the functionalities of IO-Link devices is that they can fire off events to the IO-Link master to notify that something has happened, for instance an alarm that something is wrong. To integrate these IO-link devices (slaves) into your EtherCAT network you need an IO-Link master, which usually allows you to connect 4 or 8 IO-Link slaves.
Test driven development (TDD) doesn’t seem to be all too common among TwinCAT-developers, which is a shame. From my experience, TDD has a strong foothold everywhere among developers, but TwinCAT? Not so much. And I don’t blame them. There are TDD frameworks for C++, C#, Ada, Python and basically any other language and/or development environment. Do a Google search on the web on any programming language/IDE and TDD and you get thousands of results. Do the same for TwinCAT and you’re on your own.