Skip to content

Commit

Permalink
Merge 5b731f0 into ab47e7f
Browse files Browse the repository at this point in the history
  • Loading branch information
cormacc committed Jul 17, 2019
2 parents ab47e7f + 5b731f0 commit b80ecb0
Show file tree
Hide file tree
Showing 9 changed files with 1,511 additions and 103 deletions.
4 changes: 3 additions & 1 deletion .appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
version: '{build}-appveyor'
image: Visual Studio 2017
install:
- set PATH=C:\Ruby200\bin;%PATH%
build:
verbosity: minimal
test_script:
Expand All @@ -10,4 +12,4 @@ test_script:
C:\projects\fff\test\ms_vc_fff_test\x64\Debug\ms_vc_fff_test_global_cpp.exe
C:\projects\fff\test\ms_vc_fff_test\x64\Debug\ms_vc_fff_test_global_c.exe
C:\projects\fff\test\ms_vc_fff_test\x64\Debug\ms_vc_fff_test_global_c.exe
136 changes: 127 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,16 @@ FAKE_VOID_FUNC(DISPLAY_init);
And the unit test might look something like this:
```c
TEST_F(GreeterTests, init_initialises_display)
{
UI_init();
FFF_ASSERT_CALLS(DISPLAY_init, 1);
}
```

... or ...

```c
TEST_F(GreeterTests, init_initialises_display)
{
Expand Down Expand Up @@ -101,6 +111,17 @@ FAKE_VOID_FUNC(DISPLAY_output, char *);

And the unit test might look something like this:

```c
TEST_F(UITests, write_line_outputs_lines_to_display)
{
char msg[] = "helloworld";
UI_write_line(msg);
FFF_ASSERT(DISPLAY_output, msg);
}
```
... or ...
```c
TEST_F(UITests, write_line_outputs_lines_to_display)
{
Expand All @@ -111,7 +132,6 @@ TEST_F(UITests, write_line_outputs_lines_to_display)
}
```

There is no more magic here, the `FAKE_VOID_FUNC` works as in the
previous example. The number of arguments that the function takes is calculated,
and the macro arguments following the function name defines the argument
Expand All @@ -120,7 +140,23 @@ type (a char pointer in this example).
A variable is created for every argument in the form
`"function_name"fake.argN_val`

## Return Values
### Variadic argument assertions

These are a recent addition to the framework. The range of available assertions is
listed in the cheat sheet at the foot of this page. The assertions use a simple
assertion macro defined internally. To override with a macro from some test framework,
do the following in some header you include in all your tests:

```c
// my_test_framework_header.h
...
#define _FFF_ASSERT_EQ_MSG(expected, actual, message) MY_CUSTOM_ASSERTION(expected, actual, message)
#include "fff.h"
...
```
## Return values
When you want to define a fake function that returns a value, you should use the
`FAKE_VALUE_FUNC` macro. For instance:
Expand All @@ -142,6 +178,21 @@ FAKE_VALUE_FUNC(unsigned int, DISPLAY_get_line_insert_index);
And the unit test might look something like this:
```c
TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen)
{
// given
FFF_RETURN(DISPLAY_get_line_insert_index,1);
char msg[] = "helloworld";
// when
UI_write_line(msg);
// then
FFF_ASSERT_NOT_CALLED(DISPLAY_clear);
}
```
... or ...
```c
TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen)
{
Expand All @@ -167,7 +218,37 @@ you would use a syntax like this:
```c
FAKE_VALUE_FUNC(double, pow, double, double);
```
## Resetting a Fake
*N.B.* When using the variadic form (i.e. `FFF_RETURN(FN, ...)`), the hidden value sequence array
is declared locally by default. If you want to set a return sequence in a function other than
the test body (e.g. in a fixture setup method or helper function used in multiple tests), you'll
need to prefix the macro invocation with the `static` keyword. e.g.

```c
void setup(void)
{
// given
static FFF_RETURN(DISPLAY_get_line_insert_index, 1, 2, 3);
}

TEST_F(UITests, when_empty_lines_write_line_doesnt_clear_screen)
{
...
//Some test logic exercising DISPLAY_get_line_insert_index
...
}

TEST_F(UITests, when_empty_lines_write_line_bla)
{
...
//Some more test logic exercising DISPLAY_get_line_insert_index
...
}
```
The static keyword is not necessary when specifying a single value, as the macro uses the dedicated struct member in this case.
## Resetting a fake
Good tests are isolated tests, so it is important to reset the fakes for each
unit test. All the fakes have a reset function to reset their arguments and
Expand Down Expand Up @@ -237,6 +318,18 @@ They are reset by calling `FFF_RESET_HISTORY();`
The framework will by default store the arguments for the last ten calls made
to a fake function.

```c
TEST_F(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history)
{
voidfunc2('g', 'h');
voidfunc2('i', 'j');
FFF_ASSERT_NTH(voidfunc2, 1, 'g', 'h');
FFF_ASSERT_NTH(voidfunc2, 2, 'i', 'j');
}
```
... or ...
```c
TEST_F(FFFTestSuite, when_fake_func_called_then_arguments_captured_in_history)
{
Expand Down Expand Up @@ -298,6 +391,21 @@ with for the fake function. It is probably easier to describe with an example:
// faking "long longfunc();"
FAKE_VALUE_FUNC(long, longfunc0);

TEST_F(FFFTestSuite, return_value_sequences_exhausted)
{
FFF_RETURN(longfunc0, myReturnVals, 3, 7, 9);
ASSERT_EQ(3, longfunc0());
ASSERT_EQ(7, longfunc0());
ASSERT_EQ(9, longfunc0());
ASSERT_EQ(9, longfunc0());
ASSERT_EQ(9, longfunc0());
}
```
... or ...
```c
// faking "long longfunc();"
FAKE_VALUE_FUNC(long, longfunc0);
TEST_F(FFFTestSuite, return_value_sequences_exhausted)
{
long myReturnVals[3] = { 3, 7, 9 };
Expand Down Expand Up @@ -638,10 +746,20 @@ So whats the point?
## Cheat Sheet
| Macro | Description | Example |
|-------|-------------|---------|
| FAKE_VOID_FUNC(fn [,arg_types*]); | Define a fake function named fn returning void with n arguments | FAKE_VOID_FUNC(DISPLAY_output_message, const char*); |
| FAKE_VALUE_FUNC(return_type, fn [,arg_types*]); | Define a fake function returning a value with type return_type taking n arguments | FAKE_VALUE_FUNC(int, DISPLAY_get_line_insert_index); |
| FAKE_VOID_FUNC_VARARG(fn [,arg_types*], ...); | Define a fake variadic function returning void with type return_type taking n arguments and n variadic arguments | FAKE_VOID_FUNC_VARARG(fn, const char*, ...) |
| Macro | Description | Example |
|-------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------|
| FAKE_VOID_FUNC(fn [,arg_types*]); | Define a fake function named fn returning void with n arguments | FAKE_VOID_FUNC(DISPLAY_output_message, const char*); |
| FAKE_VALUE_FUNC(return_type, fn [,arg_types*]); | Define a fake function returning a value with type return_type taking n arguments | FAKE_VALUE_FUNC(int, DISPLAY_get_line_insert_index); |
| FAKE_VOID_FUNC_VARARG(fn [,arg_types*], ...); | Define a fake variadic function returning void with type return_type taking n arguments and n variadic arguments | FAKE_VOID_FUNC_VARARG(fn, const char*, ...) |
| FAKE_VALUE_FUNC_VARARG(return_type, fn [,arg_types*], ...); | Define a fake variadic function returning a value with type return_type taking n arguments and n variadic arguments | FAKE_VALUE_FUNC_VARARG(int, fprintf, FILE*, const char*, ...) |
| RESET_FAKE(fn); | Reset the state of fake function called fn | RESET_FAKE(DISPLAY_init); |
| RESET_FAKE(fn); | Reset the state of fake function called fn | RESET_FAKE(DISPLAY_init); |
| FFF_RETURN(fn, ...return_value(s)*); | Set one or more return values (final value repeated if calls > values) | FFF_RETURN(DISPLAY_init, 1, 2, 3); |
| FFF_ASSERT_CALLED(fn); | Assert that a function was called once and only once. | FFF_ASSERT_CALLED(DISPLAY_init); |
| FFF_ASSERT_NOT_CALLED(fn); | Assert that a function was not called. | FFF_ASSERT_NOT_CALLED(DISPLAY_init); |
| FFF_ASSERT_CALLS(fn, call_count); | Assert that a function was called the specified number of times. | FFF_ASSERT_CALLS(DISPLAY_init, 3); |
| FFF_ASSERT(fn, ...arg_value(s)) | Assert that a function was called only once with the specified argument values. | FFF_ASSERT(DISPLAY_output_message, my_message_ptr); |
| FFF_ASSERT_LAST(fn, ...arg_value(s)) | Assert that the last call to a function had the specified argument values. | FFF_ASSERT_LAST(DISPLAY_output_message, my_message_ptr); |
| FFF_ASSERT_ANY(fn, ...arg_value(s)) | Assert that any call to a function had the specified argument values. | FFF_ASSERT_ANY(DISPLAY_output_message, my_message_ptr); |
| FFF_ASSERT_NONE(fn, ...arg_value(s)) | Assert that no calls to a function had the specified argument values. | FFF_ASSERT_NONE(DISPLAY_output_message, my_message_ptr); |
*N.B.* All of the function argument assertions support partial specification of arguments. I.e. Given a function taking 3 args, you may just specify the first argument for verification. Any arguments that are specified must be specified from left to right however. i.e. it is possibly to specify arguments 0 and 1, but not arguments 0 and 2 (ignoring the value of 1).
2 changes: 1 addition & 1 deletion buildandtest
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ echo >> fff.h
ruby fakegen.rb >> fff.h
make clean
make all
build/fff_test_c
build/fff_test_c
build/fff_test_cpp --gtest_output=xml:build/test_results.xml
build/ui_test_ansic
build/ui_test_cpp --gtest_output=xml:build/example_results.xml
Expand Down

0 comments on commit b80ecb0

Please sign in to comment.