DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Last call! Secure your stack and shape the future! Help dev teams across the globe navigate their software supply chain security challenges.

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Releasing software shouldn't be stressful or risky. Learn how to leverage progressive delivery techniques to ensure safer deployments.

Avoid machine learning mistakes and boost model performance! Discover key ML patterns, anti-patterns, data strategies, and more.

Related

  • Testing Serverless Functions
  • Microservices Testing: Key Strategies and Tools
  • How to Become a DevOps Engineer
  • Test-Driven Development With The oclif Testing Library: Part One

Trending

  • Unlocking AI Coding Assistants Part 2: Generating Code
  • Breaking Bottlenecks: Applying the Theory of Constraints to Software Development
  • Stateless vs Stateful Stream Processing With Kafka Streams and Apache Flink
  • Doris: Unifying SQL Dialects for a Seamless Data Query Ecosystem
  1. DZone
  2. Data Engineering
  3. AI/ML
  4. Testing State Machines — The Model-Driven Approach

Testing State Machines — The Model-Driven Approach

Following the model-driven paradigm, state machines are first modeled on an abstract level and in a second step transformed into source code.

By 
Thomas Kutz user avatar
Thomas Kutz
·
Updated Mar. 11, 20 · Tutorial
Likes (3)
Comment
Save
Tweet
Share
7.8K Views

Join the DZone community and get the full member experience.

Join For Free

When developing complex reactive systems, state machines are often used to describe and implement the logic of a software component. Following the model-driven paradigm, state machines are first modeled on an abstract level and in a second step transformed into source code.

This has several advantages, as on the abstract level a different representation of the state machine can be used, as a two-dimensional one with boxes and arrows, also known as a state diagram or a statechart. This allows for a better understanding of the modeled system, also for non-technical persons.

You may also like: A Simple State Machine for Spring Boot Projects

When it comes to testing and debugging, it depends on good tool support if the model-based approach is a win or a hurdle for the development team.

circuit board

Photo by Nicolas Thomas on Unsplash

Status Quo

Even if the model-driven approach is followed, testing and debugging often happens on code level as the modeling tool does not support these activities adequately. As the state machine code is generated to be in sync with the model, bugs first need to be found in the code and afterward translated into the abstract model level to be fixed there.

This translation is often a manual task. Some tools may provide a tracing between model and code parts to easier find the model part for a given defective code part. A bug is seldom located in a single line of code. In most cases, a larger part of the code, and hence of the model, needs to be adjusted. Tools that allow testing the model itself in an automated way can save a lot of time here.

Once the generated state machine code is incorporated in a software component, testing is often performed on the component or application level. To test the component it is somehow stimulated by an input, which implies stimulation of the inner state machine.

The state machine reacts and communicates back with the component, for example by sending an event, which eventually invokes some application code whose side effects can be checked in the test method. This is not the same as directly testing the state machine.

In case of a failed test it is not clear whether the state machine itself is faulty, or its integration with the application code. Here again, testing the state machine already on the model level helps to identify problems early in the development process and also allows the reuse of state machines for different applications without rewriting the tests.

Quo Vadis? How Can We Do Better?

As explained above, testing state machines on the model level is more beneficial to the development process than testing on the code level. The obvious prerequisite for this is that the state machine model is executable. Testing the model is only possible if one can interact with it by sending events which then provoke a reaction of the state machine that can be checked.

Once the state machine model is executable, you can interact with it manually or write scripts to perform interaction patterns automatically. Manual interaction can be used for early testing, already while modeling. This is the same as if you were running your application while coding to check if your code works.

The ability to execute the state machine model allows to already verify it before any application code is written. This allows to speed up your development cycles as changes in the state machine logic do not need to be reflected in the application code until the state machine has a stable state.

The next logical step is to automate the manual interaction with the model. Automated tests ensure that model changes do not break existing functionality. Ideally, these tests reflect the requirements on the state machine logic. When requirements are added or changed, they can be translated into test cases first which leads towards a test-driven development approach on model level.

Once we have a bunch of executable tests for our state machine, the next step is to evaluate the quality of the test set. This is typically done with the help of coverage metrics. There are several coverage metrics, like statement coverage or branch coverage; however, when it comes to measuring the coverage based on a state machine model, we want to know which states are activated, and which transitions are taken by our test cases.

This helps to identify redundant test cases as well as writing new test cases that add some value in terms of test coverage.

Tool Support for Model-Driven State Machine Testing

Model-driven state machine testing is not feasible without adequate tool support. The ability to execute and test a model requires the ability to interpret a state machine model just as if it were code that is interpreted by an interpreter. YAKINDU Statechart Tools comes with exactly that ability. The graphical state machine models created with YAKINDU Statechart Tools can be executed and tested already on the model level.

Executable State Machines

YAKINDU Statechart Tools allow executing the modeled state machine in a simulator. The simulator allows the user to raise events or to set variable values. The reaction of the state machine is directly reflected in the model by highlighting the active state(s).

The simulation view lists all variables and their values. Furthermore, the user can set breakpoints and create snapshots to restart the simulation at a specific point of execution. This allows to easily verify the modeled behavior already while modeling the state machine.

Simulation of state machine model in YAKINDU Statechart Tools

Test Automation With Statechart Unit Tests

YAKINDU Statechart Tools comes with a scripting language (SCTUnit) that allows writing tests comprehensively and compactly. Each test, written in the SCTUnit language, consists of a well-defined sequence of instructions. When running a test, these instructions are applied to a state machine under control. The expected reaction of the state machine is expressed by assertions. With the SCTUnit language you can:

  • Raise incoming events
  • Change values of variables
  • Assert that a state is active
  • Assert that a variable has a certain value
  • Assert that an operation has been called with certain input values
  • Assert how often an operation has been called
  • Define simple operation mocks
  • Virtually proceed time or run-to-completion cycles

Here is an example of a test case written in SCTUnit:


code snippet

Explaining the details of SCTUnit is out of the scope of this article. If you are interested, you can read the documentation or watch this video by Professor Tom Mens.

Test Coverage on the Fly

When a test set is executed, a model coverage is computed on the fly and visualized in the state machine model. This allows to easily identify missing tests. For example, from the coverage metric below, it is obvious that none of the tests has brought the state machine into the Save Energy state. Once we add a corresponding test and run the test set again, the Save Energy state gets green.

test coverage
Visualization of test coverage metric

Summary

Testing state machines on the model level requires a tool that can execute the state machine model. If such a tool is available, it can help a lot to test and debug the state machine logic which in the long term saves you time and money.

YAKINDU Statechart Tools fulfill` this requirement. It allows simulating a state machine manually, as well as writing unit tests to automate test execution. The built-in test coverage metric gives a visual hint on the quality of the test set.


Further Reading

A Non-Blocking State Machine
Machine unit test application

Published at DZone with permission of Thomas Kutz. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Testing Serverless Functions
  • Microservices Testing: Key Strategies and Tools
  • How to Become a DevOps Engineer
  • Test-Driven Development With The oclif Testing Library: Part One

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!