mirror of
https://github.com/ThrowTheSwitch/Unity.git
synced 2025-05-17 15:36:21 +08: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.
|
||||
- The structure of Unity allows you to easily separate test assertions from
|
||||
source code in, well, test code.
|
||||
- Unity's assertions:
|
||||
- Come in many, many flavors to handle different C types and assertion cases.
|
||||
- Use context to provide detailed and helpful failure messages.
|
||||
- Document types, expected values, and basic behavior in your source code for
|
||||
- Unity’s assertions:
|
||||
- Come in many, many flavors to handle different C types and assertion cases.
|
||||
- Use context to provide detailed and helpful failure messages.
|
||||
- Document types, expected values, and basic behavior in your source code for
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
picture on this read up on the difference between
|
||||
[link:Dynamic Verification and Static Analysis]). A failing assertion stops
|
||||
execution and reports an error through some appropriate I/O channel (e.g.
|
||||
stdout, GUI, file, blinky light).
|
||||
or not? You get the idea. Assertions are executable code. Static analysis is a
|
||||
valuable approach to improving code quality, but it is not executing your code
|
||||
in the way an assertion can. A failing assertion stops execution and reports an
|
||||
error through some appropriate I/O channel (e.g. stdout, GUI, output file,
|
||||
blinky light).
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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,
|
||||
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
|
||||
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
|
||||
@ -73,12 +73,12 @@ a simple null check).
|
||||
- `Actual` is the value being tested and unlike the other parameters in an
|
||||
assertion construction is the only parameter present in all assertion variants.
|
||||
- `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
|
||||
`actual` parameter (e.g. null check).
|
||||
- `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
|
||||
messages are presented. For instance, a `_HEX` variant of an assertion prints
|
||||
the expected and actual values of that assertion formatted as hexadecimal.
|
||||
@ -99,7 +99,7 @@ _Example:_
|
||||
TEST_ASSERT_X( {modifiers}, {expected}, actual, {size/count} )
|
||||
```
|
||||
|
||||
becomes messageified like thus...
|
||||
becomes messageified like thus…
|
||||
|
||||
```c
|
||||
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:
|
||||
|
||||
- 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
|
||||
message, if necessary.
|
||||
- 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
|
||||
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
|
||||
memory.
|
||||
|
||||
@ -144,7 +144,7 @@ Notes:
|
||||
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
|
||||
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.
|
||||
|
||||
```c
|
||||
@ -203,7 +203,7 @@ code then verifies as a final step.
|
||||
#### `TEST_PASS_MESSAGE("message")`
|
||||
|
||||
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
|
||||
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)`
|
||||
|
||||
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
|
||||
differ, the assertion fails. Two NULL strings (i.e. zero length) are considered
|
||||
equivalent.
|
||||
@ -561,7 +561,7 @@ Asserts that the `actual` value is NOT within +/- `delta` of the `expected` valu
|
||||
|
||||
#### `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
|
||||
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
|
||||
@ -569,7 +569,7 @@ code generation conventions for CMock.
|
||||
|
||||
#### `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.
|
||||
|
||||
#### `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)`
|
||||
|
||||
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
|
||||
Asserting section for more details. Omitting a user-specified delta in a
|
||||
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)`
|
||||
|
||||
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.
|
||||
|
||||
#### `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
|
||||
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
|
||||
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
|
||||
equality checks to fail.
|
||||
|
||||
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
|
||||
running with defaults, "really close" means "within a significant bit or two."
|
||||
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
|
||||
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`
|
||||
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
|
||||
@ -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
|
||||
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
|
||||
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.
|
||||
|
||||
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
|
||||
0 x 20 or 0 x 263.It's still zero, right? Luckily, if you
|
||||
subtract these values from each other, they will always produce a difference of
|
||||
zero, which will still fall between 0 plus or minus a delta of 0. So it still
|
||||
works!
|
||||
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
|
||||
0x20 or 0x263. It’s still zero, right? Luckily, if you subtract these
|
||||
values from each other, they will always produce a difference of zero, which
|
||||
will still fall between 0 plus or minus a delta of 0. So it still works!
|
||||
|
||||
Double precision floating point numbers use a much smaller multiplier, again
|
||||
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
|
||||
defining UNITY_FLOAT_PRECISION and UNITY_DOUBLE_PRECISION. See Unity
|
||||
documentation for more.
|
||||
|
||||
### 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
|
||||
varies by target. According to the C standard, an `int` is to be the target's
|
||||
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
|
||||
natural register size, and it should be at least 16-bits and a multiple of a
|
||||
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
|
||||
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
|
||||
situations, they often choose the natural register size, leaving us with
|
||||
something like this:
|
||||
@ -823,24 +822,24 @@ something like this:
|
||||
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.
|
||||
|
||||
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'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
|
||||
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
|
||||
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
|
||||
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
|
||||
(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
|
||||
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
|
||||
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.
|
||||
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
|
||||
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.
|
||||
|
Reference in New Issue
Block a user