{"id":19633423,"url":"https://github.com/electronvector/fake_function_framework","last_synced_at":"2025-04-28T07:30:51.024Z","repository":{"id":48295909,"uuid":"59451675","full_name":"ElectronVector/fake_function_framework","owner":"ElectronVector","description":"A plug-in for Ceedling to use the Fake Function Framework (fff) for mocking instead of Cmock. ","archived":false,"fork":false,"pushed_at":"2021-08-02T21:29:25.000Z","size":429,"stargazers_count":38,"open_issues_count":7,"forks_count":13,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-05T07:33:05.664Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ElectronVector.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-23T04:19:44.000Z","updated_at":"2024-12-04T14:34:22.000Z","dependencies_parsed_at":"2022-09-19T00:41:50.592Z","dependency_job_id":null,"html_url":"https://github.com/ElectronVector/fake_function_framework","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElectronVector%2Ffake_function_framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElectronVector%2Ffake_function_framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElectronVector%2Ffake_function_framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ElectronVector%2Ffake_function_framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ElectronVector","download_url":"https://codeload.github.com/ElectronVector/fake_function_framework/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251271086,"owners_count":21562489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T12:17:19.543Z","updated_at":"2025-04-28T07:30:49.848Z","avatar_url":"https://github.com/ElectronVector.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# A Fake Function Framework Plug-in for Ceedling\n\n[![Build Status](https://travis-ci.com/ElectronVector/fake_function_framework.svg?branch=master)](https://travis-ci.com/ElectronVector/fake_function_framework)\n\nThis is a plug-in for [Ceedling](https://github.com/ThrowTheSwitch/Ceedling) to use the [Fake Function Framework](https://github.com/meekrosoft/fff) for mocking instead of CMock.\n\nUsing fff provides less strict mocking than CMock, and allows for more loosely-coupled tests.\nAnd, when tests fail -- since you get the actual line number of the failure -- it's a lot easier to figure out what went wrong.\n\n## Installing the plug-in\n\nThis fff plugin should already be included with your Ceedling installation, but to use it on a project you first need to enable it in your project.yml file.\n\n### Enable the plug-in\n\nThis plug-in needs to be enabled from within your project.yml file. It is not enabled by default.\n\nIn the `:plugins` configuration, add `fake_function_framework` to the list of enabled plugins.\n\n```yaml\n:plugins:\n  :enabled:\n    - stdout_pretty_tests_report\n    - module_generator\n    - fake_function_framework # \u003c-- Enable it here.\n```\n\n### Get the latest version of this plugin\n\nYou may want to get the latest source of this plug if the version in your Ceedling release is not up-to-date.\n\nThe easiest way to do this is to clone this repo into the Ceedling plugin folder.\n\nTypically Ceedling is used from its gem installation folder, which is where you will want to clone this repo. You can determine where Ceedling is intalled on your machine by running:\n\n```\n$ gem list -d -e ceedling\n\n*** LOCAL GEMS ***\n\nceedling (0.30.0)\n    Authors: Mark VanderVoord, Michael Karlesky, Greg Williams\n    Homepage: http://throwtheswitch.org/ceedling\n    License: MIT\n    Installed at: /var/lib/gems/2.7.0\n\n    Ceedling is a build automation tool for C unit test suites that\n    packages up Unity, CMock, and Rake-based build management\n    functionality\n```\n\nIn this case you would want to install in `/var/lib/gems/2.7.0/gems/ceedling-0.30.0/plugins/fake_function_framework`.\n\nRemove any existing `fake_function_framework` folder and then clone the contents of this repo into it with (run from the `/var/lib/gems/2.7.0/gems/ceedling-0.30.0/plugins` folder):\n\n```\ngit clone --recurse https://github.com/ElectronVector/fake_function_framework.git\n```\n\nThis will create a new folder named `fake_function_framework` in the plugins folder.\n\n#### Installing it somewhere else\n\nYou could also install it somewhere else on your machine and tell Ceedling where it is in the project.yml file with the `:load_paths:` setting:\n\n```yaml\n:plugins:\n  :load_paths:\n    - /some/other/place/for/plugins # \u003c-- Your custom path.\n  :enabled:\n    - stdout_pretty_tests_report\n    - module_generator\n    - fake_function_framework\n```\n\n#### Using with Ceedling installed in the project\n\nIf you have an older project with Ceedling running from an installation inside of the project folder, then you'll need to clone into the project `vendor/ceedling/plugins/fake_function_framework` folder instead.\n\nYou'll also need to set the load path correctly for this situation.\n\n```yaml\n:plugins:\n  :load_paths:\n    - vendor/ceedling/plugins # \u003c-- Your project plugin folder.\n```\n\n## How to use it\n\nYou use fff with Ceedling the same way you used to use CMock.\nModules can still be generated with the default module generator: `rake module:create[my_module]`.\nIf you want to \"mock\" `some_module.h` in your tests, just `#include \"mock_some_module.h\"`.\nThis creates a fake function for each of the functions defined in `some_module.h`.\n\nThe name of each fake is the original function name with an appended `_fake`.\nFor example, if we're generating fakes for a stack module with `push` and `pop` functions, we would have the fakes `push_fake` and `pop_fake`.\nThese fakes are linked into our test executable so that any time our unit under test calls `push` or `pop` our fakes are called instead.\n\nEach of these fakes is actually a structure containing information about how the function was called, and what it might return.\nWe can use Unity to inspect these fakes in our tests, and verify the interactions of our units.\nThere is also a global structure named `fff` which we can use to check the sequence of calls.\n\nThe fakes can also be configured to return particular values, so you can exercise the unit under test however you want.\n\nThe examples below explain how to use fff to test a variety of module interactions.\nEach example uses fakes for a \"display\" module, created from a display.h file with `#include \"mock_display.h\"`. The `display.h` file must exist and must contain the prototypes for the functions to be faked.\n\n### Test that a function was called once\n\n```c\nvoid\ntest_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()\n{\n    // When\n    event_deviceReset();\n\n    // Then\n    TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);\n}\n```\n\n### Test that a function was NOT called\n\n```c\nvoid\ntest_whenThePowerReadingIsLessThan5_thenTheStatusLedIsNotTurnedOn(void)\n{\n    // When\n    event_powerReadingUpdate(4);\n\n    // Then\n    TEST_ASSERT_EQUAL(0, display_turnOnStatusLed_fake.call_count);\n}\n```\n\n## Test that a single function was called with the correct argument\n\n```c\nvoid\ntest_whenTheVolumeKnobIsMaxed_thenVolumeDisplayIsSetTo11(void)\n{\n    // When\n    event_volumeKnobMaxed();\n\n    // Then\n    TEST_ASSERT_EQUAL(1, display_setVolume_fake.call_count);\n    TEST_ASSERT_EQUAL(11, display_setVolume_fake.arg0_val);\n}\n```\n\n## Test that calls are made in a particular sequence\n\n```c\nvoid\ntest_whenTheModeSelectButtonIsPressed_thenTheDisplayModeIsCycled(void)\n{\n    // When\n    event_modeSelectButtonPressed();\n    event_modeSelectButtonPressed();\n    event_modeSelectButtonPressed();\n\n    // Then\n    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMinimum, fff.call_history[0]);\n    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToMaximum, fff.call_history[1]);\n    TEST_ASSERT_EQUAL_PTR((void*)display_setModeToAverage, fff.call_history[2]);\n}\n```\n\n## Fake a return value from a function\n\n```c\nvoid\ntest_givenTheDisplayHasAnError_whenTheDeviceIsPoweredOn_thenTheDisplayIsPoweredDown(void)\n{\n    // Given\n    display_isError_fake.return_val = true;\n\n    // When\n    event_devicePoweredOn();\n\n    // Then\n    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);\n}\n```\n\n## Fake a function with a value returned by reference\n\n```c\nvoid\ntest_givenTheUserHasTypedSleep_whenItIsTimeToCheckTheKeyboard_theDisplayIsPoweredDown(void)\n{\n    // Given\n    char mockedEntry[] = \"sleep\";\n    void return_mock_value(char * entry, int length)\n    {\n        if (length \u003e strlen(mockedEntry))\n        {\n            strncpy(entry, mockedEntry, length);\n        }\n    }\n    display_getKeyboardEntry_fake.custom_fake = return_mock_value;\n\n    // When\n    event_keyboardCheckTimerExpired();\n\n    // Then\n    TEST_ASSERT_EQUAL(1, display_powerDown_fake.call_count);\n}\n```\n\n## Fake a function with a function pointer parameter\n\n```\nvoid\ntest_givenNewDataIsAvailable_whenTheDisplayHasUpdated_thenTheEventIsComplete(void)\n{\n    // A mock function for capturing the callback handler function pointer.\n    void(*registeredCallback)(void) = 0;\n    void mock_display_updateData(int data, void(*callback)(void))\n    {\n        //Save the callback function.\n        registeredCallback = callback;\n    }\n    display_updateData_fake.custom_fake = mock_display_updateData;\n\n    // Given\n    event_newDataAvailable(10);\n\n    // When\n    if (registeredCallback != 0)\n    {\n        registeredCallback();\n    }\n\n    // Then\n    TEST_ASSERT_EQUAL(true, eventProcessor_isLastEventComplete());\n}\n```\n\n## Helper macros\n\nFor convenience, there are also some helper macros that create new Unity-style asserts:\n\n- `TEST_ASSERT_CALLED(function)`: Asserts that a function was called once.\n- `TEST_ASSERT_NOT_CALLED(function)`: Asserts that a function was never called.\n- `TEST_ASSERT_CALLED_TIMES(times, function)`: Asserts that a function was called a particular number of times.\n- `TEST_ASSERT_CALLED_IN_ORDER(order, function)`: Asserts that a function was called in a particular order.\n\nHere's how you might use one of these instead of simply checking the call_count value:\n\n```c\nvoid\ntest_whenTheDeviceIsReset_thenTheStatusLedIsTurnedOff()\n{\n    // When\n    event_deviceReset();\n\n    // Then\n    // This how to directly use fff...\n    TEST_ASSERT_EQUAL(1, display_turnOffStatusLed_fake.call_count);\n    // ...and this is how to use the helper macro.\n    TEST_ASSERT_CALLED(display_turnOffStatusLed);\n}\n```\n\n## Test setup\n\nAll of the fake functions, and any fff global state are all reset automatically between each test.\n\n## CMock configuration\n\nUse still use some of the CMock configuration options for setting things like the mock prefix, and for including additional header files in the mock files.\n\n```yaml\n:cmock:\n    :mock_prefix: mock_\n        :includes:\n            -\n        :includes_h_pre_orig_header:\n            -\n        :includes_h_post_orig_header:\n            -\n        :includes_c_pre_header:\n            -\n        :includes_c_post_header:\n```\n\n## Plugin developer tools: Running the tests\n\nThere are unit and integration tests for the plug-in itself.\nThese are run with the default `rake` task.\nThe integration test runs the tests for the example project in examples/fff_example.\n\n## More examples\n\nThere is an example project in examples/fff_example.\nIt shows how to use the plug-in with some full-size examples.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectronvector%2Ffake_function_framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felectronvector%2Ffake_function_framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felectronvector%2Ffake_function_framework/lists"}