Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 (GCC only) 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 (GCC only) 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)) | (GCC only) 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)) | (GCC only) 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
Loading