C/C++ Samples: Difference between revisions

From STRIDE Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 31: Line 31:
This is the place  to start for on target tests in native code. These samples are meant to  serve as a basic overview of many native testing features and  techniques. If you are interested in writing tests in C/C++ that run on  the device, we recommend building and running these tests, then reviewing the test source code test output.
This is the place  to start for on target tests in native code. These samples are meant to  serve as a basic overview of many native testing features and  techniques. If you are interested in writing tests in C/C++ that run on  the device, we recommend building and running these tests, then reviewing the test source code test output.


;[[Test Intro Sample]]
;[[Test Intro Sample]]
: For C-only  environments this is the place to start. These samples are meant to  serve as a basic overview of many STRIDE testing features and techniques from a C perspective. If you haven't already done so, we recommend  building and running these tests, then reviewing the test source code  test output. The process of including this sample as well as running it and publishing results is covered in [[Building_an_Off-Target_Test_App | building a Off-Target TestApp]] article.
: For C-only  environments this is the place to start. These samples are meant to  serve as a basic overview of many STRIDE testing features and techniques from a C perspective. If you haven't already done so, we recommend  building and running these tests, then reviewing the test source code  test output. The process of including this sample as well as running it and publishing results is covered in [[Building_an_Off-Target_Test_App | building a Off-Target TestApp]] article.


;[[Test Intro Cpp Sample]]
;[[Test Intro Cpp Sample]]
: For C++  environments this is the place to start. The samples provide a basic  overview of many STRIDE testing features and techniques from a C++ perspective.
: For C++  environments this is the place to start. The samples provide a basic  overview of many STRIDE testing features and techniques from a C++ perspective.


Line 44: Line 44:
If you have selected the type of test unit you will be using, we recommend you review and run the corresponding sample. If you are still deciding which type of test unit packaging to use, feel free to peruse all three samples as well as the corresponding [[Test Units|documentation]].
If you have selected the type of test unit you will be using, we recommend you review and run the corresponding sample. If you are still deciding which type of test unit packaging to use, feel free to peruse all three samples as well as the corresponding [[Test Units|documentation]].


;[[Test_Class_Samples | Test Class Samples]] ''(C++ only)''
;[[Test_Class_Sample | Test Class Sample]] ''(C++ only)''
: Demonstrates features available when [[Test Units|test units]] are created as C++ classes
: Demonstrates features available when [[Test Units|test units]] are created as C++ classes
;[[Test_CClass_Samples | Test C Class Samples]]
;[[Test_CClass_Sample | Test C Class Sample]]
: Demonstrates how to create and use [[Test Units|test units]] that are C structures
: Demonstrates how to create and use [[Test Units|test units]] that are C structures
;[[Test_Function_List_Samples  | Test Function List Samples]]
;[[Test_Function_List_Sample | Test Function List Sample]]
: Demonstrates how to create and use [[Test Units|test units]] that are free C functions
: Demonstrates how to create and use [[Test Units|test units]] that are free C functions


Line 57: Line 57:
Pass/Fail Macros simplify the  task of setting a test case's status to pass or fail. They comprise a  set of ASSERTs and EXPECTs that test a condition (e.g. equailty, less  than, strings equal, etc.) and set the currently running test to the  appropriate pass or fail status. ASSERTs cause the currently executing function to immediately return if fail status is set; EXPECTs do not return.
Pass/Fail Macros simplify the  task of setting a test case's status to pass or fail. They comprise a  set of ASSERTs and EXPECTs that test a condition (e.g. equailty, less  than, strings equal, etc.) and set the currently running test to the  appropriate pass or fail status. ASSERTs cause the currently executing function to immediately return if fail status is set; EXPECTs do not return.
   
   
;[[Test_Macros_Samples  | Test  Macros Samples]]
;[[Test_Macros_Sample | Test  Macros Sample]]
: Demonstrates  the use of the [[Test Code Macros]]. This sample is implemented using Test Classes (''C++ only''), but these macros also work in C compilation units.
: Demonstrates  the use of the [[Test Code Macros]]. This sample is implemented using Test Classes (''C++ only''), but these macros also work in C compilation units.


Line 66: Line 66:
Test points are a unique STRIDE feature that greatly simplifies testing of multi-threaded software as well as single-threaded software that employs callbacks.
Test points are a unique STRIDE feature that greatly simplifies testing of multi-threaded software as well as single-threaded software that employs callbacks.


;[[Test  Point Samples]]
;[[Test  Point Sample]]
: Demonstrates  techniques and syntax for implementing [[Test Point Testing in C/C++ |Test Points]]. With this technique, STRIDE makes it possible to observe and verify activity occurring another thread (e.g. a state machine).
: Demonstrates  techniques and syntax for implementing [[Test Point Testing in C/C++ |Test Points]]. With this technique, STRIDE makes it possible to observe and verify activity occurring another thread (e.g. a state machine).


Line 72: Line 72:
Test doubles provide a means to  intercept function calls so that alternate implementations can be  substituted at runtime under the control of your test code. This enables  sophisticated mocking, faking, and stubbing.
Test doubles provide a means to  intercept function calls so that alternate implementations can be  substituted at runtime under the control of your test code. This enables  sophisticated mocking, faking, and stubbing.


;[[Test_Double_Samples | Test Double Samples]]
;[[Test_Double_Sample | Test Double Sample]]
: Demonstrates  techniques and syntax for implementing [[Using Test  Doubles|Test Doubles]]. STRIDE's unique implementation makes it possible to dynamically switch in function mocks, stubs, and fakes at runtime. This sample is implemented using Test Classes (''C++ only''), but the techniques demonstrated work equally well in C compilation units.
: Demonstrates  techniques and syntax for implementing [[Using Test  Doubles|Test Doubles]]. STRIDE's unique implementation makes it possible to dynamically switch in function mocks, stubs, and fakes at runtime. This sample is implemented using Test Classes (''C++ only''), but the techniques demonstrated work equally well in C compilation units.


Line 78: Line 78:
The STRIDE File Services APIs provide a means to perform basic filesystem operations on the host  filesystem from test code running on a device.  
The STRIDE File Services APIs provide a means to perform basic filesystem operations on the host  filesystem from test code running on a device.  


;[[File_Services_Samples  | File Services Samples]]
;[[File_Services_Sample | File Services Sample]]
: Demonstrates  techniques and syntax for performing basic tasks using the [[File Transfer Services|File Transfer  Services API]].
: Demonstrates  techniques and syntax for performing basic tasks using the [[File Transfer Services|File Transfer  Services API]].



Revision as of 15:50, 9 June 2011

Background

The STRIDE Framework provides support for implementation of tests in the native C/C++ of the device under test. These samples are a collection of source code that demonstrate the techniques for creating and executing target-based (native code) tests using the STRIDE Framework. Once written, these tests are compiled using the device toolchain and are harnessed, via the STRIDE Intercept Module, into one or more applications under test on the device. These tests have the unique advantage of executing in real-time on the device itself, allowing the tests to operate under actual device conditions during test.

Please review the following reference articles before proceeding:

Why would I want to write tests in native code ?

Here are some of the scenarios for which on-target test harnessing is particularly advantageous:

  • direct API testing. If you want to validate native APIs by driving the APIs directly, native code is the simplest way to do so. STRIDE provides convenient assertion macros to validate your variable states. API testing can also be combined with native test point tests (using Test Point instrumentation) to provide deeper validation of expected behavior of the units under test.
  • unit testing of C objects or C++ classes. The STRIDE native tests execute in the same context as the rest of your code, so it's possible to fully unit test any objects that can be created in your actual application code.
  • validation logic that requires sensitive timing thresholds. Sometimes it's only possible to validate tight timing scenarios on-target.
  • high-volume data processing scenarios. In some cases, the volume of data being processed and validated for a particular test scenario is to large to be easily handled by an off-target harness. In that case, native test units provide a convenient way to write tests that validate that data without shipping the data to the host during testing.

What's more, you might simply prefer to write your test logic in C or C++ (as opposed to perl on the host). If that's the case, we don't discourage you from using a toolset that your more comfortable with - particularly if it enables you to start writing tests without a new language learning curve.

Are there any disadvantages ?

Sure. Most of the disadvantages of native on-target tests concern the device build process. If your device build is particularly slow (on the order of hours or days), then adding and running new tests can become a tedious waiting game. Testing is always well served by shorter build cycles, and on-target tests are particularly sensitive to this.

In some cases, the additional code space requirements of native tests is a concern, but this is also mitigated by ever-increasing device storage capacities. On platforms that support multiple processes (e.g. embedded linux or WinMobile), it's possible to bundle tests into one or more separate test process, which further mitigates the code space concern by isolating the test code in one or more separate applications.

Introductory Samples

This is the place to start for on target tests in native code. These samples are meant to serve as a basic overview of many native testing features and techniques. If you are interested in writing tests in C/C++ that run on the device, we recommend building and running these tests, then reviewing the test source code test output.

Test Intro Sample
For C-only environments this is the place to start. These samples are meant to serve as a basic overview of many STRIDE testing features and techniques from a C perspective. If you haven't already done so, we recommend building and running these tests, then reviewing the test source code test output. The process of including this sample as well as running it and publishing results is covered in building a Off-Target TestApp article.
Test Intro Cpp Sample
For C++ environments this is the place to start. The samples provide a basic overview of many STRIDE testing features and techniques from a C++ perspective.

Test Unit Packaging Samples

Test Unit Packaging refers to how functions or methods implementing test cases are packaged into test units. It's possible for different packaging options to coexist, but for consistency and simplicity, we recommend that you decide early on in your test creation cycle what kind of test unit package you will use for your test units and then stick with that for all of your test units.

If your compiler supports standard C++, the Test Class packaging is preferred as it allows the greatest functionality and flexibility with no added complexity for the simplest use cases.[1] (Note that the Test Class packaging can be used even if the software under test is written in C.)

If you have selected the type of test unit you will be using, we recommend you review and run the corresponding sample. If you are still deciding which type of test unit packaging to use, feel free to peruse all three samples as well as the corresponding documentation.

Test Class Sample (C++ only)
Demonstrates features available when test units are created as C++ classes
Test C Class Sample
Demonstrates how to create and use test units that are C structures
Test Function List Sample
Demonstrates how to create and use test units that are free C functions

Common Testing Features Samples

These samples demonstrate features that are frequently used in common testing scenarios. All developers creating or maintaining tests should be familiar with the techniques shown in these samples.

Pass/Fail Macros

Pass/Fail Macros simplify the task of setting a test case's status to pass or fail. They comprise a set of ASSERTs and EXPECTs that test a condition (e.g. equailty, less than, strings equal, etc.) and set the currently running test to the appropriate pass or fail status. ASSERTs cause the currently executing function to immediately return if fail status is set; EXPECTs do not return.

Test Macros Sample
Demonstrates the use of the Test Code Macros. This sample is implemented using Test Classes (C++ only), but these macros also work in C compilation units.

Advanced Testing Features Samples

The features demonstrated in these samples target specific testing problems.

Test Points

Test points are a unique STRIDE feature that greatly simplifies testing of multi-threaded software as well as single-threaded software that employs callbacks.

Test Point Sample
Demonstrates techniques and syntax for implementing Test Points. With this technique, STRIDE makes it possible to observe and verify activity occurring another thread (e.g. a state machine).

Test Doubles

Test doubles provide a means to intercept function calls so that alternate implementations can be substituted at runtime under the control of your test code. This enables sophisticated mocking, faking, and stubbing.

Test Double Sample
Demonstrates techniques and syntax for implementing Test Doubles. STRIDE's unique implementation makes it possible to dynamically switch in function mocks, stubs, and fakes at runtime. This sample is implemented using Test Classes (C++ only), but the techniques demonstrated work equally well in C compilation units.

File Services

The STRIDE File Services APIs provide a means to perform basic filesystem operations on the host filesystem from test code running on a device.

File Services Sample
Demonstrates techniques and syntax for performing basic tasks using the File Transfer Services API.

Notes

  1. If your C++ compiler supports exceptions and/or namespaces, STRIDE can take advantage of the added capabilities, but these are not required