mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2026-01-23 08:25:58 +01:00
Documentation improvements
* Fixed a broken markdown bulleted list * Replaced a missing document link (from the original source of this documentation) with a full sentence explaining the relation of `assert()` to static analysis. * Typographic fixes * Replaced single and double straight quotes with smart quotes where appropriate * Replaced three periods with ellipses where appropriate
This commit is contained in:
@@ -10,46 +10,46 @@ Upon boolean False, an assertion stops execution and reports the failure.
|
|||||||
and easily execute those assertions.
|
and easily execute those assertions.
|
||||||
- The structure of Unity allows you to easily separate test assertions from
|
- The structure of Unity allows you to easily separate test assertions from
|
||||||
source code in, well, test code.
|
source code in, well, test code.
|
||||||
- Unity's assertions:
|
- Unity’s assertions:
|
||||||
- Come in many, many flavors to handle different C types and assertion cases.
|
- Come in many, many flavors to handle different C types and assertion cases.
|
||||||
- Use context to provide detailed and helpful failure messages.
|
- Use context to provide detailed and helpful failure messages.
|
||||||
- Document types, expected values, and basic behavior in your source code for
|
- Document types, expected values, and basic behavior in your source code for
|
||||||
free.
|
free.
|
||||||
|
|
||||||
### Unity Is Several Things But Mainly It's Assertions
|
### Unity Is Several Things But Mainly It’s Assertions
|
||||||
|
|
||||||
One way to think of Unity is simply as a rich collection of assertions you can
|
One way to think of Unity is simply as a rich collection of assertions you can
|
||||||
use to establish whether your source code behaves the way you think it does.
|
use to establish whether your source code behaves the way you think it does.
|
||||||
Unity provides a framework to easily organize and execute those assertions in
|
Unity provides a framework to easily organize and execute those assertions in
|
||||||
test code separate from your source code.
|
test code separate from your source code.
|
||||||
|
|
||||||
### What's an Assertion?
|
### What’s an Assertion?
|
||||||
|
|
||||||
At their core, assertions are an establishment of truth - boolean truth. Was this
|
At their core, assertions are an establishment of truth - boolean truth. Was this
|
||||||
thing equal to that thing? Does that code doohickey have such-and-such property
|
thing equal to that thing? Does that code doohickey have such-and-such property
|
||||||
or not? You get the idea. Assertions are executable code (to appreciate the big
|
or not? You get the idea. Assertions are executable code. Static analysis is a
|
||||||
picture on this read up on the difference between
|
valuable approach to improving code quality, but it is not executing your code
|
||||||
[link:Dynamic Verification and Static Analysis]). A failing assertion stops
|
in the way an assertion can. A failing assertion stops execution and reports an
|
||||||
execution and reports an error through some appropriate I/O channel (e.g.
|
error through some appropriate I/O channel (e.g. stdout, GUI, output file,
|
||||||
stdout, GUI, file, blinky light).
|
blinky light).
|
||||||
|
|
||||||
Fundamentally, for dynamic verification all you need is a single assertion
|
Fundamentally, for dynamic verification all you need is a single assertion
|
||||||
mechanism. In fact, that's what the [assert() macro][] in C's standard library
|
mechanism. In fact, that’s what the [assert() macro][] in C’s standard library
|
||||||
is for. So why not just use it? Well, we can do far better in the reporting
|
is for. So why not just use it? Well, we can do far better in the reporting
|
||||||
department. C's `assert()` is pretty dumb as-is and is particularly poor for
|
department. C’s `assert()` is pretty dumb as-is and is particularly poor for
|
||||||
handling common data types like arrays, structs, etc. And, without some other
|
handling common data types like arrays, structs, etc. And, without some other
|
||||||
support, it's far too tempting to litter source code with C's `assert()`'s. It's
|
support, it’s far too tempting to litter source code with C’s `assert()`’s. It’s
|
||||||
generally much cleaner, manageable, and more useful to separate test and source
|
generally much cleaner, manageable, and more useful to separate test and source
|
||||||
code in the way Unity facilitates.
|
code in the way Unity facilitates.
|
||||||
|
|
||||||
### Unity's Assertions: Helpful Messages _and_ Free Source Code Documentation
|
### Unity’s Assertions: Helpful Messages _and_ Free Source Code Documentation
|
||||||
|
|
||||||
Asserting a simple truth condition is valuable, but using the context of the
|
Asserting a simple truth condition is valuable, but using the context of the
|
||||||
assertion is even more valuable. For instance, if you know you're comparing bit
|
assertion is even more valuable. For instance, if you know you’re comparing bit
|
||||||
flags and not just integers, then why not use that context to give explicit,
|
flags and not just integers, then why not use that context to give explicit,
|
||||||
readable, bit-level feedback when an assertion fails?
|
readable, bit-level feedback when an assertion fails?
|
||||||
|
|
||||||
That's what Unity's collection of assertions do - capture context to give you
|
That’s what Unity’s collection of assertions do - capture context to give you
|
||||||
helpful, meaningful assertion failure messages. In fact, the assertions
|
helpful, meaningful assertion failure messages. In fact, the assertions
|
||||||
themselves also serve as executable documentation about types and values in your
|
themselves also serve as executable documentation about types and values in your
|
||||||
source code. So long as your tests remain current with your source and all those
|
source code. So long as your tests remain current with your source and all those
|
||||||
@@ -73,12 +73,12 @@ a simple null check).
|
|||||||
- `Actual` is the value being tested and unlike the other parameters in an
|
- `Actual` is the value being tested and unlike the other parameters in an
|
||||||
assertion construction is the only parameter present in all assertion variants.
|
assertion construction is the only parameter present in all assertion variants.
|
||||||
- `Modifiers` are masks, ranges, bit flag specifiers, floating point deltas.
|
- `Modifiers` are masks, ranges, bit flag specifiers, floating point deltas.
|
||||||
- `Expected` is your expected value (duh) to compare to an `actual` value; it's
|
- `Expected` is your expected value (duh) to compare to an `actual` value; it’s
|
||||||
marked as an optional parameter because some assertions only need a single
|
marked as an optional parameter because some assertions only need a single
|
||||||
`actual` parameter (e.g. null check).
|
`actual` parameter (e.g. null check).
|
||||||
- `Size/count` refers to string lengths, number of array elements, etc.
|
- `Size/count` refers to string lengths, number of array elements, etc.
|
||||||
|
|
||||||
Many of Unity's assertions are clear duplications in that the same data type
|
Many of Unity’s assertions are clear duplications in that the same data type
|
||||||
is handled by several assertions. The differences among these are in how failure
|
is handled by several assertions. The differences among these are in how failure
|
||||||
messages are presented. For instance, a `_HEX` variant of an assertion prints
|
messages are presented. For instance, a `_HEX` variant of an assertion prints
|
||||||
the expected and actual values of that assertion formatted as hexadecimal.
|
the expected and actual values of that assertion formatted as hexadecimal.
|
||||||
@@ -99,7 +99,7 @@ _Example:_
|
|||||||
TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
|
TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
|
||||||
```
|
```
|
||||||
|
|
||||||
becomes messageified like thus...
|
becomes messageified like thus…
|
||||||
|
|
||||||
```c
|
```c
|
||||||
TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
|
TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
|
||||||
@@ -108,7 +108,7 @@ TEST_ASSERT_X_MESSAGE( {modifiers}, {expected}, actual, {size/count}, message )
|
|||||||
Notes:
|
Notes:
|
||||||
|
|
||||||
- The `_MESSAGE` variants intentionally do not support `printf` style formatting
|
- The `_MESSAGE` variants intentionally do not support `printf` style formatting
|
||||||
since many embedded projects don't support or avoid `printf` for various reasons.
|
since many embedded projects don’t support or avoid `printf` for various reasons.
|
||||||
It is possible to use `sprintf` before the assertion to assemble a complex fail
|
It is possible to use `sprintf` before the assertion to assemble a complex fail
|
||||||
message, if necessary.
|
message, if necessary.
|
||||||
- If you want to output a counter value within an assertion fail message (e.g. from
|
- If you want to output a counter value within an assertion fail message (e.g. from
|
||||||
@@ -119,7 +119,7 @@ Notes:
|
|||||||
|
|
||||||
Unity provides a collection of assertions for arrays containing a variety of
|
Unity provides a collection of assertions for arrays containing a variety of
|
||||||
types. These are documented in the Array section below. These are almost on par
|
types. These are documented in the Array section below. These are almost on par
|
||||||
with the `_MESSAGE`variants of Unity's Asserts in that for pretty much any Unity
|
with the `_MESSAGE`variants of Unity’s Asserts in that for pretty much any Unity
|
||||||
type assertion you can tack on `_ARRAY` and run assertions on an entire block of
|
type assertion you can tack on `_ARRAY` and run assertions on an entire block of
|
||||||
memory.
|
memory.
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ Notes:
|
|||||||
Unity provides a collection of assertions for arrays containing a variety of
|
Unity provides a collection of assertions for arrays containing a variety of
|
||||||
types which can be compared to a single value as well. These are documented in
|
types which can be compared to a single value as well. These are documented in
|
||||||
the Each Equal section below. these are almost on par with the `_MESSAGE`
|
the Each Equal section below. these are almost on par with the `_MESSAGE`
|
||||||
variants of Unity's Asserts in that for pretty much any Unity type assertion you
|
variants of Unity’s Asserts in that for pretty much any Unity type assertion you
|
||||||
can inject `_EACH_EQUAL` and run assertions on an entire block of memory.
|
can inject `_EACH_EQUAL` and run assertions on an entire block of memory.
|
||||||
|
|
||||||
```c
|
```c
|
||||||
@@ -203,7 +203,7 @@ code then verifies as a final step.
|
|||||||
#### `TEST_PASS_MESSAGE("message")`
|
#### `TEST_PASS_MESSAGE("message")`
|
||||||
|
|
||||||
This will abort the remainder of the test, but count the test as a pass. Under
|
This will abort the remainder of the test, but count the test as a pass. Under
|
||||||
normal circumstances, it is not necessary to include this macro in your tests...
|
normal circumstances, it is not necessary to include this macro in your tests…
|
||||||
a lack of failure will automatically be counted as a `PASS`. It is occasionally
|
a lack of failure will automatically be counted as a `PASS`. It is occasionally
|
||||||
useful for tests with `#ifdef`s and such.
|
useful for tests with `#ifdef`s and such.
|
||||||
|
|
||||||
@@ -392,7 +392,7 @@ Asserts that the pointers point to the same memory location.
|
|||||||
|
|
||||||
#### `TEST_ASSERT_EQUAL_STRING (expected, actual)`
|
#### `TEST_ASSERT_EQUAL_STRING (expected, actual)`
|
||||||
|
|
||||||
Asserts that the null terminated (`'\0'`)strings are identical. If strings are
|
Asserts that the null terminated (`’\0’`)strings are identical. If strings are
|
||||||
of different lengths or any portion of the strings before their terminators
|
of different lengths or any portion of the strings before their terminators
|
||||||
differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
|
differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
|
||||||
equivalent.
|
equivalent.
|
||||||
@@ -561,7 +561,7 @@ Asserts that the `actual` value is NOT within +/- `delta` of the `expected` valu
|
|||||||
|
|
||||||
#### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)`
|
#### `TEST_ASSERT_EQUAL_FLOAT (expected, actual)`
|
||||||
|
|
||||||
Asserts that the `actual` value is "close enough to be considered equal" to the
|
Asserts that the `actual` value is “close enough to be considered equal” to the
|
||||||
`expected` value. If you are curious about the details, refer to the Advanced
|
`expected` value. If you are curious about the details, refer to the Advanced
|
||||||
Asserting section for more details on this. Omitting a user-specified delta in a
|
Asserting section for more details on this. Omitting a user-specified delta in a
|
||||||
floating point assertion is both a shorthand convenience and a requirement of
|
floating point assertion is both a shorthand convenience and a requirement of
|
||||||
@@ -569,7 +569,7 @@ code generation conventions for CMock.
|
|||||||
|
|
||||||
#### `TEST_ASSERT_NOT_EQUAL_FLOAT (expected, actual)`
|
#### `TEST_ASSERT_NOT_EQUAL_FLOAT (expected, actual)`
|
||||||
|
|
||||||
Asserts that the `actual` value is NOT "close enough to be considered equal" to the
|
Asserts that the `actual` value is NOT “close enough to be considered equal” to the
|
||||||
`expected` value.
|
`expected` value.
|
||||||
|
|
||||||
#### `TEST_ASSERT_FLOAT_ARRAY_WITHIN (delta, expected, actual, num_elements)`
|
#### `TEST_ASSERT_FLOAT_ARRAY_WITHIN (delta, expected, actual, num_elements)`
|
||||||
@@ -662,7 +662,7 @@ Asserts that the `actual` value is NOT within +/- `delta` of the `expected` valu
|
|||||||
|
|
||||||
#### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)`
|
#### `TEST_ASSERT_EQUAL_DOUBLE (expected, actual)`
|
||||||
|
|
||||||
Asserts that the `actual` value is "close enough to be considered equal" to the
|
Asserts that the `actual` value is “close enough to be considered equal” to the
|
||||||
`expected` value. If you are curious about the details, refer to the Advanced
|
`expected` value. If you are curious about the details, refer to the Advanced
|
||||||
Asserting section for more details. Omitting a user-specified delta in a
|
Asserting section for more details. Omitting a user-specified delta in a
|
||||||
floating point assertion is both a shorthand convenience and a requirement of
|
floating point assertion is both a shorthand convenience and a requirement of
|
||||||
@@ -670,7 +670,7 @@ code generation conventions for CMock.
|
|||||||
|
|
||||||
#### `TEST_ASSERT_NOT_EQUAL_DOUBLE (expected, actual)`
|
#### `TEST_ASSERT_NOT_EQUAL_DOUBLE (expected, actual)`
|
||||||
|
|
||||||
Asserts that the `actual` value is NOT "close enough to be considered equal" to the
|
Asserts that the `actual` value is NOT “close enough to be considered equal” to the
|
||||||
`expected` value.
|
`expected` value.
|
||||||
|
|
||||||
#### `TEST_ASSERT_DOUBLE_ARRAY_WITHIN (delta, expected, actual, num_elements)`
|
#### `TEST_ASSERT_DOUBLE_ARRAY_WITHIN (delta, expected, actual, num_elements)`
|
||||||
@@ -753,7 +753,7 @@ Not A Number floating point representations.
|
|||||||
|
|
||||||
This section helps you understand how to deal with some of the trickier
|
This section helps you understand how to deal with some of the trickier
|
||||||
assertion situations you may run into. It will give you a glimpse into some of
|
assertion situations you may run into. It will give you a glimpse into some of
|
||||||
the under-the-hood details of Unity's assertion mechanisms. If you're one of
|
the under-the-hood details of Unity’s assertion mechanisms. If you’re one of
|
||||||
those people who likes to know what is going on in the background, read on. If
|
those people who likes to know what is going on in the background, read on. If
|
||||||
not, feel free to ignore the rest of this document until you need it.
|
not, feel free to ignore the rest of this document until you need it.
|
||||||
|
|
||||||
@@ -768,9 +768,9 @@ mathematical operations might result in a representation of 8 x 2-2
|
|||||||
that also evaluates to a value of 2. At some point repeated operations cause
|
that also evaluates to a value of 2. At some point repeated operations cause
|
||||||
equality checks to fail.
|
equality checks to fail.
|
||||||
|
|
||||||
So Unity doesn't do direct floating point comparisons for equality. Instead, it
|
So Unity doesn’t do direct floating point comparisons for equality. Instead, it
|
||||||
checks if two floating point values are "really close." If you leave Unity
|
checks if two floating point values are “really close.” If you leave Unity
|
||||||
running with defaults, "really close" means "within a significant bit or two."
|
running with defaults, “really close” means “within a significant bit or two.”
|
||||||
Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN`
|
Under the hood, `TEST_ASSERT_EQUAL_FLOAT` is really `TEST_ASSERT_FLOAT_WITHIN`
|
||||||
with the `delta` parameter calculated on the fly. For single precision, delta is
|
with the `delta` parameter calculated on the fly. For single precision, delta is
|
||||||
the expected value multiplied by 0.00001, producing a very small proportional
|
the expected value multiplied by 0.00001, producing a very small proportional
|
||||||
@@ -779,28 +779,27 @@ range around the expected value.
|
|||||||
If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So
|
If you are expecting a value of 20,000.0 the delta is calculated to be 0.2. So
|
||||||
any value between 19,999.8 and 20,000.2 will satisfy the equality check. This
|
any value between 19,999.8 and 20,000.2 will satisfy the equality check. This
|
||||||
works out to be roughly a single bit of range for a single-precision number, and
|
works out to be roughly a single bit of range for a single-precision number, and
|
||||||
that's just about as tight a tolerance as you can reasonably get from a floating
|
that’s just about as tight a tolerance as you can reasonably get from a floating
|
||||||
point value.
|
point value.
|
||||||
|
|
||||||
So what happens when it's zero? Zero - even more than other floating point
|
So what happens when it’s zero? Zero - even more than other floating point
|
||||||
values - can be represented many different ways. It doesn't matter if you have
|
values - can be represented many different ways. It doesn’t matter if you have
|
||||||
0 x 20 or 0 x 263.It's still zero, right? Luckily, if you
|
0x20 or 0x263. It’s still zero, right? Luckily, if you subtract these
|
||||||
subtract these values from each other, they will always produce a difference of
|
values from each other, they will always produce a difference of zero, which
|
||||||
zero, which will still fall between 0 plus or minus a delta of 0. So it still
|
will still fall between 0 plus or minus a delta of 0. So it still works!
|
||||||
works!
|
|
||||||
|
|
||||||
Double precision floating point numbers use a much smaller multiplier, again
|
Double precision floating point numbers use a much smaller multiplier, again
|
||||||
approximating a single bit of error.
|
approximating a single bit of error.
|
||||||
|
|
||||||
If you don't like these ranges and you want to make your floating point equality
|
If you don’t like these ranges and you want to make your floating point equality
|
||||||
assertions less strict, you can change these multipliers to whatever you like by
|
assertions less strict, you can change these multipliers to whatever you like by
|
||||||
defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
|
defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
|
||||||
documentation for more.
|
documentation for more.
|
||||||
|
|
||||||
### How do we deal with targets with non-standard int sizes?
|
### How do we deal with targets with non-standard int sizes?
|
||||||
|
|
||||||
It's "fun" that C is a standard where something as fundamental as an integer
|
It’s “fun” that C is a standard where something as fundamental as an integer
|
||||||
varies by target. According to the C standard, an `int` is to be the target's
|
varies by target. According to the C standard, an `int` is to be the target’s
|
||||||
natural register size, and it should be at least 16-bits and a multiple of a
|
natural register size, and it should be at least 16-bits and a multiple of a
|
||||||
byte. It also guarantees an order of sizes:
|
byte. It also guarantees an order of sizes:
|
||||||
|
|
||||||
@@ -814,7 +813,7 @@ and this remains perfectly standard C.
|
|||||||
|
|
||||||
To make things even more interesting, there are compilers and targets out there
|
To make things even more interesting, there are compilers and targets out there
|
||||||
that have a hard choice to make. What if their natural register size is 10-bits
|
that have a hard choice to make. What if their natural register size is 10-bits
|
||||||
or 12-bits? Clearly they can't fulfill _both_ the requirement to be at least
|
or 12-bits? Clearly they can’t fulfill _both_ the requirement to be at least
|
||||||
16-bits AND the requirement to match the natural register size. In these
|
16-bits AND the requirement to match the natural register size. In these
|
||||||
situations, they often choose the natural register size, leaving us with
|
situations, they often choose the natural register size, leaving us with
|
||||||
something like this:
|
something like this:
|
||||||
@@ -823,24 +822,24 @@ something like this:
|
|||||||
char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit)
|
char (8 bit) <= short (12 bit) <= int (12 bit) <= long (16 bit)
|
||||||
```
|
```
|
||||||
|
|
||||||
Um... yikes. It's obviously breaking a rule or two... but they had to break SOME
|
Um… yikes. It’s obviously breaking a rule or two… but they had to break SOME
|
||||||
rules, so they made a choice.
|
rules, so they made a choice.
|
||||||
|
|
||||||
When the C99 standard rolled around, it introduced alternate standard-size types.
|
When the C99 standard rolled around, it introduced alternate standard-size types.
|
||||||
It also introduced macros for pulling in MIN/MAX values for your integer types.
|
It also introduced macros for pulling in MIN/MAX values for your integer types.
|
||||||
It's glorious! Unfortunately, many embedded compilers can't be relied upon to
|
It’s glorious! Unfortunately, many embedded compilers can’t be relied upon to
|
||||||
use the C99 types (Sometimes because they have weird register sizes as described
|
use the C99 types (Sometimes because they have weird register sizes as described
|
||||||
above. Sometimes because they don't feel like it?).
|
above. Sometimes because they don’t feel like it?).
|
||||||
|
|
||||||
A goal of Unity from the beginning was to support every combination of
|
A goal of Unity from the beginning was to support every combination of
|
||||||
microcontroller or microprocessor and C compiler. Over time, we've gotten really
|
microcontroller or microprocessor and C compiler. Over time, we’ve gotten really
|
||||||
close to this. There are a few tricks that you should be aware of, though, if
|
close to this. There are a few tricks that you should be aware of, though, if
|
||||||
you're going to do this effectively on some of these more idiosyncratic targets.
|
you’re going to do this effectively on some of these more idiosyncratic targets.
|
||||||
|
|
||||||
First, when setting up Unity for a new target, you're going to want to pay
|
First, when setting up Unity for a new target, you’re going to want to pay
|
||||||
special attention to the macros for automatically detecting types
|
special attention to the macros for automatically detecting types
|
||||||
(where available) or manually configuring them yourself. You can get information
|
(where available) or manually configuring them yourself. You can get information
|
||||||
on both of these in Unity's documentation.
|
on both of these in Unity’s documentation.
|
||||||
|
|
||||||
What about the times where you suddenly need to deal with something odd, like a
|
What about the times where you suddenly need to deal with something odd, like a
|
||||||
24-bit `int`? The simplest solution is to use the next size up. If you have a
|
24-bit `int`? The simplest solution is to use the next size up. If you have a
|
||||||
@@ -848,9 +847,9 @@ What about the times where you suddenly need to deal with something odd, like a
|
|||||||
`int`, configure Unity to use 16 bits. There are two ways this is going to
|
`int`, configure Unity to use 16 bits. There are two ways this is going to
|
||||||
affect you:
|
affect you:
|
||||||
|
|
||||||
1. When Unity displays errors for you, it's going to pad the upper unused bits
|
1. When Unity displays errors for you, it’s going to pad the upper unused bits
|
||||||
with zeros.
|
with zeros.
|
||||||
2. You're going to have to be careful of assertions that perform signed
|
2. You’re going to have to be careful of assertions that perform signed
|
||||||
operations, particularly `TEST_ASSERT_INT_WITHIN`. Such assertions might wrap
|
operations, particularly `TEST_ASSERT_INT_WITHIN`. Such assertions might wrap
|
||||||
your `int` in the wrong place, and you could experience false failures. You can
|
your `int` in the wrong place, and you could experience false failures. You can
|
||||||
always back down to a simple `TEST_ASSERT` and do the operations yourself.
|
always back down to a simple `TEST_ASSERT` and do the operations yourself.
|
||||||
|
|||||||
Reference in New Issue
Block a user