Stride Overview: Difference between revisions
No edit summary |
No edit summary |
||
(2 intermediate revisions by the same user not shown) | |||
Line 39: | Line 39: | ||
Test cases are typically constructed leveraging a large set of available assertion macros. When failures occur, these macros automatically set test status and provide details to the test report such as file name, line number, and condition causing the failure. Stride provides a large set of these macros to validate a wide variety of scenarios. | Test cases are typically constructed leveraging a large set of available assertion macros. When failures occur, these macros automatically set test status and provide details to the test report such as file name, line number, and condition causing the failure. Stride provides a large set of these macros to validate a wide variety of scenarios. | ||
<source lang=cpp> | <source lang="cpp"> | ||
#include <mytest.h> | #include <mytest.h> | ||
Line 58: | Line 58: | ||
Create an INI-type of file (i.e. ''myinput.ini'') | Create an INI-type of file (i.e. ''myinput.ini'') | ||
<source lang=ini> | <source lang="ini"> | ||
Loopsize = 10 | Loopsize = 10 | ||
InputFile = ${MYPATH}/datacontent.bin | InputFile = ${MYPATH}/datacontent.bin | ||
Line 66: | Line 66: | ||
Pass the name-value collection using the Stride Runner | Pass the name-value collection using the Stride Runner | ||
<source lang=bash> | <source lang="bash"> | ||
$ stride .. --run="MyTest(/path/to/myinput.ini)" | $ stride .. --run="MyTest(/path/to/myinput.ini)" | ||
</source> | </source> | ||
Line 72: | Line 72: | ||
Now simply access your input within test logic using built-in services | Now simply access your input within test logic using built-in services | ||
<source lang=cpp> | <source lang="cpp"> | ||
{ | { | ||
// .. doing stuff .. | // .. doing stuff .. | ||
Line 88: | Line 88: | ||
For example something like the following could be useful: | For example something like the following could be useful: | ||
<source lang=cpp> | <source lang="cpp"> | ||
void MySuite::test1() | void MySuite::test1() | ||
{ | { | ||
Line 106: | Line 106: | ||
Stride leverages ''source instrumentation'' to provide an additional validation technique called '''Expectation Testing''' that can be applied to the executing software application. The execution sequencing of the code, along with state data, can be automatically validated based on ''what is expected''. This validation technique does not focus on calling functions/methods but rather verifies ''code execution sequencing''. This can span threads, process boundaries, and even multiple targets, as the application(s) is running. Leveraging simple macros -- called '''Test Points''' -- developers strategically instrument the source under test. | Stride leverages ''source instrumentation'' to provide an additional validation technique called '''Expectation Testing''' that can be applied to the executing software application. The execution sequencing of the code, along with state data, can be automatically validated based on ''what is expected''. This validation technique does not focus on calling functions/methods but rather verifies ''code execution sequencing''. This can span threads, process boundaries, and even multiple targets, as the application(s) is running. Leveraging simple macros -- called '''Test Points''' -- developers strategically instrument the source under test. | ||
<source lang= | <source lang="c"> | ||
/* a test point with formatted string payload */ | /* a test point with formatted string payload */ | ||
Line 121: | Line 121: | ||
The following is a snippet of what the test code might look like | The following is a snippet of what the test code might look like | ||
<source | <source lang="c"> | ||
srTestPointExpect_t expected[]={ | srTestPointExpect_t expected[]={ | ||
Line 143: | Line 143: | ||
'''C/C++ Test Example''' | '''C/C++ Test Example''' | ||
<source lang=cpp> | <source lang="cpp"> | ||
#include <srtest.h> | #include <srtest.h> | ||
Line 155: | Line 155: | ||
<source lang=cpp> | <source lang="cpp"> | ||
#include <mytest.h> | #include <mytest.h> | ||
Line 164: | Line 164: | ||
void MyTest::CheckBoo() { | void MyTest::CheckBoo() { | ||
.. | .. | ||
srASSERT_GT(boo(3 * 3), 7); | |||
} | } | ||
</source> | </source> | ||
Line 185: | Line 185: | ||
sub CheckBoo : Test | sub CheckBoo : Test | ||
{ | { | ||
ASSERT_GT(Remote->boo(3 * 3), 7); | |||
} | } | ||
Latest revision as of 23:40, 21 May 2021
Stride™ is an xUnit-style test framework for C/C++ software comprised of an external test Runner, Runtime source code library, and a set of Build Tools. It was designed with a specific focus on enabling tests to be executed on a device using a fully functional build.[1]
Stride's unique host-target architecture allows easier and better On-Target/Device White-box testing. Software builds automatically become more testable; facilitating deeper code coverage opportunities.[2]
Stride is also fully integrated with Testspace for test content management.
Runner
Stride includes a lightweight Runner application that is a host-based command-line utility for interactive and automated test execution. It also integrates seamlessly with Testspace for test content management.
Runtime
Stride also contains a Runtime software source package. The Runtime enables testability by integrating with the software under test along with supporting connectivity with the host system, all with minimal impact on performance or code size. The software is agnostic to the RTOS, CPU, and host/device I/O transport. It supports simple single-process devices as well as multi-process and multi-threaded environments. It can be used with software running in either user or kernel mode, including drivers. Typically the Runtime is configured as a background thread and only executes when running tests.
Build Tools
The Stride Build Tools are a set of command-line utilities that integrate with your target software build process. They preprocess standard C/C++ header files that contain Stride test declarations to auto-generate C/C++ source code comprising a custom Intercept Module. The intercept module code is then included in your target software build along with the Stride Runtime to provide fixturing and harnessing test logic as part of your build image.
Cross Platform
Stride works on virtually any target platform. Stride's cross-platform framework facilitates a unified testing approach for all team members, enabling organizations to standardize on a test workflow that is independent of the target platform being used or what branch of software is being changed.
Runtime Written in Standard C
The Stride Runtime is written in standard ANSI C on top of a simple customizable platform abstraction layer that enables it to work across platforms. It can be configured for a single process multi-threading environment or multiple process environments (i.e. Android, Linux, Windows, Embedded RTOS, etc.). It is delivered as source code to be included in the application's build system. The transport between the host and target is configurable and supports Serial and TCP/IP by default. Custom transports are also available.
The runtime has been tailored specifically for embedded applications; overhead is minimal. It consumes very little memory for table and control block storage. Resource usage is configurable and can be adjusted to conform to any limitations of the target platform.
Integrates With Your Existing Build System
Stride auto-generates intercept module harnessing and remoting functionality as C or C++ source code during the make process, removing any dependencies on specific compilers and / or processors.
Supports Off-Target Testing
Testing can also be simulated using a standard desktop computer (Windows, Linux, or FreeBSD) with no changes to test code. The Stride SDKs allow for a seamless transition between the real target and an Off-Target host environment.
Rich set of Assertions
Test cases are typically constructed leveraging a large set of available assertion macros. When failures occur, these macros automatically set test status and provide details to the test report such as file name, line number, and condition causing the failure. Stride provides a large set of these macros to validate a wide variety of scenarios.
#include <mytest.h>
void MyTest::CheckFoo() {
..
srEXPECT_EQ(foo(2 + 2), 4);
}
void MyTest::CheckBoo() {
..
srASSERT_GT(boo(3 * 3), 7);
}
Extensive Parameter Support
Parameterized testing is key to reducing test code duplication. Constructor arguments, name-value collection, and host file remoting are all supported. Stride provides an easy way for passing and accessing these types of parameters, allowing customization of test behavior at runtime.
Create an INI-type of file (i.e. myinput.ini)
Loopsize = 10
InputFile = ${MYPATH}/datacontent.bin
Toogle = On
Pass the name-value collection using the Stride Runner
$ stride .. --run="MyTest(/path/to/myinput.ini)"
Now simply access your input within test logic using built-in services
{
// .. doing stuff ..
GetParam("InputFile", buffer, size);
//.. using parameters for test logic
}
Test Doubles & Test Points
Stride offers advanced testing techniques that enable deeper and more effective testing with less effort.
Test Doubles
For more advanced testing scenarios, dependencies can be doubled. This feature provides a means for intercepting C/C++ global functions on the target and substituting a stub, fake, or mock. The substitution is all controllable via the runtime, allowing the software to continue executing normally when not running a test.
For example something like the following could be useful:
void MySuite::test1()
{
// inserting my own version of malloc()
srDOUBLE_SET(malloc, my_malloc_stub);
// calling a routine that uses malloc(). checking handled null correctly
ret_code = FuncThatUsesMalloc(42);
srEXPECT_EQ(ret_code, -1)
// restoring the real malloc()
srDOUBLE_RESET(malloc)
}
Test Points
Stride leverages source instrumentation to provide an additional validation technique called Expectation Testing that can be applied to the executing software application. The execution sequencing of the code, along with state data, can be automatically validated based on what is expected. This validation technique does not focus on calling functions/methods but rather verifies code execution sequencing. This can span threads, process boundaries, and even multiple targets, as the application(s) is running. Leveraging simple macros -- called Test Points -- developers strategically instrument the source under test.
/* a test point with formatted string payload */
srTEST_POINT_STR("IMPORTANT", "important date= %d", myVar);
The test validation is done without impacting the application's performance (the on-target test code is executed in a background thread and scripts are executed on the host machine). When failures do occur, context is provided with the file name and associated line number of the failed expectations. This type of validation can be applied to a wide-range of testing scenarios:
- State Machines
- Data flow through system components
- Sequencing between threads
- Drivers that don't return values
- and much more ...
The following is a snippet of what the test code might look like
srTestPointExpect_t expected[]={
{"IMPORTANT"}, myCheckData,
{"ANOTHER_TP"},
{0}};
// setup the expections
srTestPointSetup(expected, ..);
// start the operations
srTestPointWait(handle, 1000);
Test Implementation
Stride based tests are integrated with the existing build system enabling your software to be both fully functional and testable at the same time. The test logic is separated from the application source code and is not executed unless invoked via the Stride Runner. Any source instrumentation is only active when executing tests. The impact of built-in testability to the software application is nominal.
The test validation can be implemented in both C/C++ on the target and Perl on the host.
C/C++ Test Example
#include <srtest.h>
class MyTest {
public:
void CheckFoo();
void CheckBoo();
};
#pragma scl_test_class(MyTest)
#include <mytest.h>
void MyTest::CheckFoo() {
..
srEXPECT_EQ(foo(2 + 2), 4);
}
void MyTest::CheckBoo() {
..
srASSERT_GT(boo(3 * 3), 7);
}
Perl Script Example
use strict;
use warnings;
package MyTests;
use base qw(STRIDE::Test);
use STRIDE::Test;
sub CheckFoo : Test
{
EXPECT_EQ(Remote->foo(2 + 2), 4);
}
sub CheckBoo : Test
{
ASSERT_GT(Remote->boo(3 * 3), 7);
}
1;
Works with Testspace
Stride has been designed to fully leverage Testspace features such as test design, execution control, and test analysis. With Testspace, test content and status remain better organized and current results and progress are much easier to assess. Refer to Testspace website for more details.