{"id":31883745,"url":"https://github.com/throwtheswitch/ceedling","last_synced_at":"2026-02-17T23:14:34.903Z","repository":{"id":2316655,"uuid":"3276877","full_name":"ThrowTheSwitch/Ceedling","owner":"ThrowTheSwitch","description":"Unit testing and build system for C projects","archived":false,"fork":false,"pushed_at":"2025-07-22T03:52:05.000Z","size":9416,"stargazers_count":728,"open_issues_count":318,"forks_count":262,"subscribers_count":43,"default_branch":"master","last_synced_at":"2025-10-10T21:10:28.398Z","etag":null,"topics":["build-tool","c","cmock","mocking","unit-testing","unity"],"latest_commit_sha":null,"homepage":"https://ThrowTheSwitch.org","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"marcelor/fabric-bash-autocompletion","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ThrowTheSwitch.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"license.txt","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"ThrowTheSwitch"}},"created_at":"2012-01-26T19:53:53.000Z","updated_at":"2025-10-09T04:20:17.000Z","dependencies_parsed_at":"2023-01-14T11:00:16.512Z","dependency_job_id":"f0a3d18e-2f53-4086-97f2-17d935e001d9","html_url":"https://github.com/ThrowTheSwitch/Ceedling","commit_stats":{"total_commits":937,"total_committers":79,"mean_commits":"11.860759493670885","dds":0.7374599786552829,"last_synced_commit":"6cbf73fbcc9cbec7a149ff1d5ca73a2d2320e242"},"previous_names":[],"tags_count":329,"template":false,"template_full_name":null,"purl":"pkg:github/ThrowTheSwitch/Ceedling","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThrowTheSwitch%2FCeedling","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThrowTheSwitch%2FCeedling/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThrowTheSwitch%2FCeedling/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThrowTheSwitch%2FCeedling/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ThrowTheSwitch","download_url":"https://codeload.github.com/ThrowTheSwitch/Ceedling/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ThrowTheSwitch%2FCeedling/sbom","scorecard":{"id":141290,"data":{"date":"2025-08-11","repo":{"name":"github.com/ThrowTheSwitch/Ceedling","commit":"c50ff9dd9a73301f4c930cc37f39123f8aaa2cb8"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.6,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":10,"reason":"5 commit(s) and 15 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Security-Policy","score":10,"reason":"security policy file detected","details":["Info: security policy file detected: docs/SECURITY.md:1","Info: Found linked content: docs/SECURITY.md:1","Info: Found disclosure, vulnerability, and/or timelines in security policy: docs/SECURITY.md:1","Info: Found text in security policy: docs/SECURITY.md:1"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Code-Review","score":1,"reason":"Found 3/18 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: topLevel 'contents' permission set to 'write': .github/workflows/main.yml:26","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:40: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:49: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:55: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:136: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:145: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:151: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:227: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:233: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:266: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:279: update your workflow using https://app.stepsecurity.io/secureworkflow/ThrowTheSwitch/Ceedling/main.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/main.yml:76","Info:   0 out of   7 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: license.txt:0","Info: FSF or OSI recognized license: MIT License: license.txt:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact 1.0.2-f9398c8 not signed: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231267164","Warn: release artifact 1.0.2-d7f9c41 not signed: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231272492","Warn: release artifact 1.0.2-767aa20 not signed: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231274849","Warn: release artifact 1.0.2-21efeca not signed: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/224926132","Warn: release artifact 1.0.2-18ac62b not signed: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/224717774","Warn: release artifact 1.0.2-f9398c8 does not have provenance: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231267164","Warn: release artifact 1.0.2-d7f9c41 does not have provenance: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231272492","Warn: release artifact 1.0.2-767aa20 does not have provenance: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/231274849","Warn: release artifact 1.0.2-21efeca does not have provenance: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/224926132","Warn: release artifact 1.0.2-18ac62b does not have provenance: https://api.github.com/repos/ThrowTheSwitch/Ceedling/releases/224717774"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-mqcp-p2hv-vw6x"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 17 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-16T08:12:50.727Z","repository_id":2316655,"created_at":"2025-08-16T08:12:50.728Z","updated_at":"2025-08-16T08:12:50.728Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279011059,"owners_count":26084865,"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","status":"online","status_checked_at":"2025-10-12T02:00:06.719Z","response_time":53,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["build-tool","c","cmock","mocking","unit-testing","unity"],"created_at":"2025-10-13T03:27:12.130Z","updated_at":"2026-01-02T05:40:55.433Z","avatar_url":"https://github.com/ThrowTheSwitch.png","language":"Ruby","readme":"Ceedling ![CI](https://github.com/ThrowTheSwitch/Ceedling/workflows/CI/badge.svg)\n========\n\nWelcome to **Ceedling 1.0.1** \n\nSee the [Release Notes](docs/ReleaseNotes.md) for an overview of all that’s new \nsince the last generation of Ceedling, versions 0.3x.x, plus links to the \ndetailed Changelog and list of Breaking Changes.\n\n# 🌱 Ceedling is a handy-dandy build system for C projects\n\n## Developer-friendly release _and_ test builds\n\nCeedling can build your release artifact but is especially adept at building\nunit test suites for your C projects — even in tricky embedded systems.\n\n⭐️ **Eager to just get going? Jump to \n[📚 Documentation \u0026 Learning](#-documentation--learning) and\n[🚀 Getting Started](#-getting-started).**\n\nCeedling works the way developers want to work. It is flexible and entirely\ncommand-line driven. It drives code generation and command line tools for you.\nAll generated and framework code is easy to see and understand.\n\nCeedling’s features support all types of C development from low-level embedded\nto enterprise systems. No tool is perfect, but Ceedling can do a whole lot to \nhelp you and your team produce quality software.\n\n## Supporting this work\n\nCeedling and its complementary [ThrowTheSwitch] pieces and parts are and always \nwill be freely available and open source.\n\n💼 **_[Ceedling Suite][ceedling-suite]_** is a growing collection of paid \nproducts and services built around Ceedling to help you do even more.\n**_[Ceedling Assist][ceedling-assist]_** for support contracts and training \nis now available.\n\n🙏🏻 **[Please consider supporting Ceedling as a Github Sponsor][tts-sponsor]**\n\n[ThrowTheSwitch]: https://github.com/ThrowTheSwitch\n[ceedling-suite]: https://www.thingamabyte.com/ceedling\n[ceedling-assist]: https://www.thingamabyte.com/ceedlingassist\n[tts-sponsor]: https://github.com/sponsors/ThrowTheSwitch\n\n## Ceedling is a suite of tools\n\nCeedling is also a suite of tools. It is the glue for bringing together three \nother awesome open-source projects you can’t live without if you‘re creating \nawesomeness in the C language.\n\n1. **[Unity]**, an [xUnit]-style test framework.\n1. **[CMock]**\u003csup\u003e†\u003c/sup\u003e, a code generating, \n   [function mocking \u0026 stubbing][test-doubles] kit for interaction-based testing.\n1. **[CException]**, a framework for adding simple exception handling to C projects\n   in the style of higher-order programming languages.\n\n\u003csup\u003e†\u003c/sup\u003e Through a [plugin][FFF-plugin], Ceedling also supports [FFF] for \n[fake functions][test-doubles] as an alternative to CMock’s mocks and stubs.\n\n## But, wait. There’s more.\n\nFor simple project structures, Ceedling can build and test an entire project\nfrom just a few lines in its project configuration file.\n\nBecause it handles all the nitty-gritty of rebuilds and becuase of Unity and\nCMock, Ceedling makes [Test-Driven Development][TDD] in C a breeze. It even \nprovides handy backtrace debugging options for finding the source of crashing\ncode exercised by your unit tests.\n\nCeedling is extensible with a simple plugin mechanism. It comes with a\nnumber of [built-in plugins][ceedling-plugins] for code coverage, test suite\nreport generation, Continuous Integration features, IDE integration, release\nlibrary builds \u0026 dependency management, and more.\n\n[Unity]: https://github.com/throwtheswitch/unity\n[xUnit]: https://en.wikipedia.org/wiki/XUnit\n[CMock]: https://github.com/throwtheswitch/cmock\n[CException]: https://github.com/throwtheswitch/cexception\n[TDD]: http://en.wikipedia.org/wiki/Test-driven_development\n[test-doubles]: https://blog.pragmatists.com/test-doubles-fakes-mocks-and-stubs-1a7491dfa3da\n[FFF]: https://github.com/meekrosoft/fff\n[FFF-plugin]: plugins/fff\n[ceedling-plugins]: docs/CeedlingPacket.md#ceedling-plugins\n\n\u003cbr/\u003e\n\n# 🙋‍♀️ Need Help? Want to Help?\n\n* Found a bug or want to suggest a feature?\n  **[Submit an issue][ceedling-issues]** at this repo.\n* Trying to understand features or solve a testing problem? Hit the\n  **[discussion forums][forums]**.\n* Paid training, customizations, and support contracts are available through \n  **[Ceedling Assist][ceedling-assist]**.\n\nThe ThrowTheSwitch community follows a **[code of conduct](docs/CODE_OF_CONDUCT.md)**.\n\nPlease familiarize yourself with our guidelines for **[contributing](docs/CONTRIBUTING.md)** to this project, be it code, reviews, documentation, or reports.\n\nYes, work has begun on **[Ceedling Certified][ceedling-certified]**, a validated version of Ceedling to meet the needs of industry software certification.\n\n[ceedling-issues]: https://github.com/ThrowTheSwitch/Ceedling/issues\n[forums]: https://www.throwtheswitch.org/forums\n[ceedling-certified]: https://www.thingamabyte.com/ceedlingcertified\n\n\u003cbr/\u003e\n\n# 🧑‍🍳 Sample Unit Testing Code\n\nWhile Ceedling can build your release artifact, its claim to fame is building and running test suites.\n\nThere’s a good chance you’re looking at Ceedling because of its test suite abilities. And, you’d probably like to see what that looks like, huh? Well, let’s cook you up some realistic examples of tested code and running Ceedling with that code.\n\n(A sample Ceedling project configuration file and links to documentation for it are a bit further down in _[🚀 Getting Started](#-getting-started)_.)\n\n## First, we start with servings of source code to be tested…\n\n### Recipe.c\n\n```c\n#include \"Recipe.h\"\n#include \"Kitchen.h\"\n#include \u003cstdio.h\u003e\n\n#define MAX_SPICE_COUNT (4)\n#define MAX_SPICE_AMOUNT_TSP (8.0f)\n\nstatic float spice_amount = 0;\nstatic uint8_t spice_count = 0;\n\nvoid Recipe_Reset(char* recipe, size_t size) {\n  memset(recipe, 0, size);\n  spice_amount = 0;\n  spice_count = 0;\n}\n\n// Add ingredients to a spice list string with amounts (tsp.)\nbool_t Recipe_BuildSpiceListTsp(char* list, size_t maxLen, SpiceId spice, float amount) {\n  if ((++spice_count \u003e MAX_SPICE_COUNT) || ((spice_amount += amount) \u003e MAX_SPICE_AMOUNT_TSP)) {\n    snprintf( list, maxLen, \"Too spicy!\" );\n    return FALSE;\n  }\n\n  // Kitchen_Ingredient() not shown\n  snprintf( list + strlen(list), maxLen, \"%s\\n\", Kitchen_Ingredient( spice, amount, TEASPOON ) );\n  return TRUE;\n}\n```\n\n### Baking.c\n\n```c\n#include \"Oven.h\"\n#include \"Time.h\"\n#include \"Baking.h\"\n\nbool_t Baking_PreheatOven(float setTempF, duration_t timeout) {\n  float temperature = 0.0;\n  Timer* timer = Time_StartTimer( timeout );\n  \n  Oven_SetTemperatureF( setTempF );\n\n  while (temperature \u003c setTempF) {\n    Time_SleepMs( 250 );\n    if (Time_IsTimerExpired( timer )) break;\n    temperature = Oven_GetTemperatureReadingF();\n  }\n\n  return (temperature \u003e= setTempF);\n}\n\n```\n\n## Next, a sprinkle of unit test code…\n\nSome of what Ceedling does is by naming conventions. See Ceedling’s [documentation](#-documentation--learning) for much more on this.\n\n### TestRecipe.c\n\n```c\n#include \"unity.h\"   // Unity, unit test framework\n#include \"Recipe.h\"  // By convention, Recipe.c is part of TestRecipe executable build\n#include \"Kitchen.h\" // By convention, Kitchen.c (not shown) is part of TestRecipe executable build\n\nchar recipe[100];\n\nvoid setUp(void) {\n  // Execute reset before each test case\n  Recipe_Reset( recipe, sizeof(recipe) );\n}\n\nvoid test_Recipe_BuildSpiceListTsp_shouldBuildSpiceList(void) {\n  TEST_ASSERT_TRUE( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), OREGANO, 0.5 ) );\n  TEST_ASSERT_TRUE( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), ROSEMARY, 1.0 ) );\n  TEST_ASSERT_TRUE( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), THYME, 0.33 ) );\n  TEST_ASSERT_EQUAL_STRING( \"1/2 tsp. Oregano\\n1 tsp. Rosemary\\n1/3 tsp. Thyme\\n\", recipe );\n}\n\nvoid test_Recipe_BuildSpiceListTsp_shouldFailIfTooMuchSpice(void) {\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), CORIANDER, 4.0 ) );\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), BLACK_PEPPER, 4.0 ) );\n  // Total spice = 8.0 + 0.1 tsp.\n  TEST_ASSERT_FALSE( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), BASIL, 0.1 ) );\n  TEST_ASSERT_EQUAL_STRING( \"Too spicy!\", recipe );\n}\n\nvoid test_Recipe_BuildSpiceListTsp_shouldFailIfTooManySpices(void) {\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), OREGANO, 1.0 ) );\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), CORIANDER, 1.0 ) );\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), BLACK_PEPPER, 1.0 ) );\n  TEST_ASSERT_TRUE ( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), THYME, 1.0 ) );\n  // Attempt to add 5th spice\n  TEST_ASSERT_FALSE( Recipe_BuildSpiceListTsp( recipe, sizeof(recipe), BASIL, 1.0 ) );\n  TEST_ASSERT_EQUAL_STRING( \"Too spicy!\", recipe );\n}\n```\n\n### TestBaking.c\n\nLet’s flavor our test code with a dash of mocks as well…\n\n```c\n#include \"unity.h\"    // Unity, unit test framework\n#include \"Baking.h\"   // By convention, Baking.c is part of TestBaking executable build\n#include \"MockOven.h\" // By convention, mock .h/.c code generated from Oven.h by CMock\n#include \"MockTime.h\" // By convention, mock .h/.c code generated from Time.h by CMock\n\n/*\n * 🚫 This test will fail! Find the missing logic in `Baking_PreheatOven()`.\n * (`Oven_SetTemperatureF()` returns success / failure.)\n */\nvoid test_Baking_PreheatOven_shouldFailIfSettingOvenTemperatureFails(void) {\n  Timer timer; // Uninitialized struct\n\n  Time_StartTimer_ExpectAndReturn( TWENTY_MIN, \u0026timer );\n\n  // Tell source code that setting the oven temperature did not work\n  Oven_SetTemperatureF_ExpectAndReturn( 350.0, FALSE );\n\n  TEST_ASSERT_FALSE( Baking_PreheatOven( 350.0, TWENTY_MIN ) );\n}\n\nvoid test_Baking_PreheatOven_shouldFailIfTimeoutExpires(void) {\n  Timer timer; // Uninitialized struct\n\n  Time_StartTimer_ExpectAndReturn( TEN_MIN, \u0026timer );\n\n  Oven_SetTemperatureF_ExpectAndReturn( 200.0, TRUE );\n\n  // We only care that `sleep()` is called, not necessarily every call to it\n  Time_SleepMs_Ignore();\n\n  // Unrolled loop of timeout and temperature checks\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 100.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 105.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 110.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, TRUE );\n\n  TEST_ASSERT_FALSE( Baking_PreheatOven( 200.0, TEN_MIN ) );  \n}\n\nvoid test_Baking_PreheatOven_shouldSucceedAfterAWhile(void) {\n  Timer timer; // Uninitialized struct\n\n  Time_StartTimer_ExpectAndReturn( TEN_MIN, \u0026timer );\n\n  Oven_SetTemperatureF_ExpectAndReturn( 400.0, TRUE );\n\n  // We only care that `sleep()` is called, not necessarily every call to it\n  Time_SleepMs_Ignore();\n\n  // Unrolled loop of timeout and temperature checks\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 390.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 395.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 399.0 );\n  Time_IsTimerExpired_ExpectAndReturn( \u0026timer, FALSE );\n  Oven_GetTemperatureReadingF_ExpectAndReturn( 401.0 );\n\n  TEST_ASSERT_TRUE( Baking_PreheatOven( 400.0, TEN_MIN ) );\n}\n```\n\n## Add a pinch of command line…\n\nSee Ceedling’s [documentation](#-documentation--learning) for examples and everything you need to know about Ceedling’s configuration file options (not shown here).\n\nThe super duper short version is that your project configuration file tells Ceedling where to find test and source files, what testing options you’re using, sets compilation symbols and build tool flags, enables your plugins, and configures your build tool command lines (Ceedling defaults to using the GNU compiler collection — which must be installed, if used).\n\n```shell\n \u003e ceedling test:all\n```\n\n## Voilà! Test results. `#ChefsKiss`\n\nThe test results below are one of the last bits of logging Ceedling produces for a test suite build. Not shown here are all the steps for extracting build details, C code generation, and compilation and linking.\n\n```\n-------------------\nFAILED TEST SUMMARY\n-------------------\n[test/TestBaking.c]\n  Test: test_Baking_PreheatOven_shouldFailIfSettingOvenTemperatureFails\n  At line (7): \"Function Time_SleepMs() called more times than expected.\"\n\n-----------------------\n❌ OVERALL TEST SUMMARY\n-----------------------\nTESTED:  6\nPASSED:  5\nFAILED:  1\nIGNORED: 0\n```\n\n## Ceedling also supports various side dishes in your delicious test suite\n\nThe Unity project supports parameterized test cases like this:\n\n```C\nTEST_RANGE([5, 100, 5])\nvoid test_should_handle_divisible_by_5_for_parameterized_test_range(int num) {\n  TEST_ASSERT_EQUAL(0, (num % 5));\n}\n```\n\nCeedling can do all the magic to build and run this test code simply by enabling parameterized test cases in its project configuration. Keep reading for more on how to configure a Ceedling build.\n\n```yaml\n:unity:\n  :use_param_tests: TRUE\n```\n\n\u003cbr/\u003e\n\n# 📚 Documentation \u0026 Learning\n\nA variety of options for [community-based support][TTS-help] exist.\n\nTraining and support contracts are available through **_[Ceedling Assist][ceedling-assist]_**\n\n[TTS-help]: https://www.throwtheswitch.org/#help-section\n\nThe [Agile Embedded Podcast][ae-podcast] includes an [episode on Ceedling][ceedling-episode]!\n\n[ae-podcast]: https://agileembeddedpodcast.com/\n[ceedling-episode]: https://agileembeddedpodcast.com/episodes/ceedling\n\n## Ceedling docs\n\n* **_[Ceedling Packet][ceedling-packet]_** is Ceedling’s user manual. It also references and links to the documentation of the projects, _Unity_, _CMock_, and _CException_, that it weaves together into your test and release builds.\n* **[Release Notes][release-notes]**, **[Breaking Changes][breaking-changes]**, and **[Changelog][changelog]** can be found in the **[docs/](docs/)** directory along with a variety of guides and much more.\n* The **[Plugins section](https://github.com/ThrowTheSwitch/Ceedling/blob/test/ceedling_0_32_rc/docs/CeedlingPacket.md#ceedling-plugins)** within _Ceedling Packet_ lists all of Ceedling’s built-in plugins providing overviews and links to their documentation.\n\n_Note:_ Check the [Release Notes][release-notes] for a “cheat sheet” illustrating project configuration option changes for new releases in the form of a Ceedling project YAML configuration file. This may be especially useful to those already familiar with the tool wanting to update to the latest and greatest as quickly as possible.\n\n## Library and courses\n\n[ThrowTheSwitch.org][TTS]:\n\n* Provides a small but useful **[library of resources and guides][library]** on testing and using the Ceedling suite of tools.\n* Discusses your **[options for running a test suite][running-options]**, particularly in the context of embedded systems.\n* Links to paid courses, **_[Dr. Surly’s School for Mad Scientists][courses]_**, that provide in-depth training on creating C unit tests and using Unity, CMock, and Ceedling to do so.\n\n## Online tutorial\n\nMatt Chernosky’s **[detailed tutorial][tutorial]** demonstrates using Ceedling to build a C project with test suite. As the tutorial is a number of years old, the content is a bit out of date. That said, it provides an excellent overview of a real project. Matt is the author of [FFF].\n\n[ceedling-packet]: docs/CeedlingPacket.md\n[release-notes]: docs/ReleaseNotes.md\n[breaking-changes]: docs/BreakingChanges.md\n[changelog]: docs/Changelog.md\n[TTS]: https://throwtheswitch.org\n[library]: http://www.throwtheswitch.org/library\n[running-options]: http://www.throwtheswitch.org/build/which\n[courses]: http://www.throwtheswitch.org/dr-surlys-school\n[tutorial]: http://www.electronvector.com/blog/add-unit-tests-to-your-current-project-with-ceedling\n\n\u003cbr/\u003e\n\n# 🚀 Getting Started\n\n👀 See the **_[Quick Start](docs/CeedlingPacket.md#quick-start)_** section in Ceedling’s user manual, _Ceedling Packet_.\n\n## The basics\n\n### Local installation from the RubyGems repository\n\n1. Install [Ruby]. (Only Ruby 3+ supported.)\n1. Install the Ceedling gem from the RubyGems repository. All supporting frameworks are included and this style of installation installs dependencies as well.\n   ```shell\n   \u003e gem install ceedling\n   ```\n1. Begin crafting your project:\n   1. Create an empty Ceedling project.\n      ```shell\n      \u003e ceedling new \u003cname\u003e [\u003cdestination path\u003e]\n      ```\n   1. Or, add a Ceedling project file to the root of an existing code project.\n1. Run tasks like so:\n   ```shell\n   \u003e ceedling test:all release\n   ```\n### Local installation of the .gem file downloaded from this repo\n\nIf you are working with prerelease versions of Ceedling or some other off-the-beaten-path installation scenario, you may want to directly install the Ceedling .gem file attached to any of the Github releases. No problem.\n\nThe steps are similar to the preceding with two changes:\n\n1. `gem install --local \u003cceedling .gem filepath\u003e`\n1. Any missing dependencies must be manually installed before installation of the local Ceedling gem will succeed. A local installation attempt will complain about any missing dependencies. Simply `gem install` them by name.\n\n[Ruby]: https://www.ruby-lang.org/\n\n### _MadScienceLab_ Docker Images\n\nAs an alternative to local installation, fully packaged Docker images containing Ruby, Ceedling, the GCC toolchain, and more are also available. [Docker][docker-overview] is a virtualization technology that provides self-contained software bundles that are a portable, well-managed alternative to local installation of tools like Ceedling.\n\nFour Docker image variants containing Ceedling and supporting tools exist. These four images are available for both Intel and ARM host platforms (Docker does the right thing based on your host environment). The latter includes ARM Linux and Apple’s M-series macOS devices.\n\n1. **_[MadScienceLab][docker-image-base]_**. This image contains Ruby, Ceedling, CMock, Unity, CException, the GNU Compiler Collection (gcc), and a handful of essential C libraries and command line utilities.\n1. **_[MadScienceLab Plugins][docker-image-plugins]_**. This image contains all of the above plus the command line tools that Ceedling’s built-in plugins rely on. Naturally, it is quite a bit larger than option (1) because of the additional tools and dependencies.\n1. **_[MadScienceLab ARM][docker-image-arm]_**. This image mirrors (1) with the compiler toolchain replaced with the GNU `arm-none-eabi` variant. \n1. **_[MadScienceLab ARM + Plugins][docker-image-arm-plugins]_**. This image is (3) with the addition of all the complementary plugin tooling just like (2) provides.\n\nSee the Docker Hub pages linked above for more documentation on these images.\n\nJust to be clear here, most users of the _MadScienceLab_ Docker images will probably care about the ability to run unit tests on your own host. If you are one of those users, no matter what host platform you are on — Intel or ARM — you’ll want to go with (1) or (2) above. The tools within the image will automatically do the right thing within your environment. Options (3) and (4) are most useful for specialized cross-compilation scenarios.\n\n#### _MadScienceLab_ Docker Image usage basics\n\nTo use a _MadScienceLab_ image from your local terminal:\n\n1. [Install Docker][docker-install]\n1. Determine:\n   1. The local path of your Ceedling project\n   1. The variant and revision of the Docker image you’ll be using\n1. Run the container with:\n   1. The Docker `run` command and `-it --rm` command line options\n   1. A Docker volume mapping from the root of your project to the default project path inside the container (_/home/dev/project_)\n\nSee the command line examples in the following two sections.\n\nNote that all of these somewhat lengthy command lines lend themselves well to being wrapped up in simple helper scripts specific to your project and directory structure.\n\n#### Run a _MadScienceLab_ Docker Image as an interactive terminal\n\nWhen the container launches as shown below, it will drop you into a Z-shell command line that has access to all the tools and utilities available within the container. In this usage, the Docker container becomes just another terminal, including ending its execution with `exit`.\n\n```shell\n \u003e docker run -it --rm -v /my/local/project/path:/home/dev/project throwtheswitch/madsciencelab-plugins:1.0.0\n```\n\nOnce the _MadScienceLab_ container’s command line is available, to run Ceedling, execute it just as you would after installing Ceedling locally:\n\n```shell\n ~/project \u003e ceedling help\n```\n\n```shell\n ~/project \u003e ceedling new ...\n```\n\n```shell\n ~/project \u003e ceedling test:all\n```\n\n#### Run a _MadScienceLab_ Docker Image as a command line utility\n\nAlternatively, you can run Ceedling through the _MadScienceLab_ Docker container directly from the command line as a command line utility. The general pattern is immediately below.\n\n```shell\n \u003e docker run --rm -v /my/local/project/path:/home/dev/project throwtheswitch/madsciencelab-plugins:1.0.0 \u003cCeedling command line\u003e\n```\n\nAs a specific example, to run all tests in a suite, the command line would be this:\n\n```shell\n \u003e docker run --rm -v /my/local/project/path:/home/dev/project throwtheswitch/madsciencelab-plugins:1.0.0 ceedling test:all\n```\n\nIn this usage, the container starts, executes Ceedling, and then ends.\n\n[docker-overview]: https://www.ibm.com/topics/docker\n[docker-install]: https://www.docker.com/products/docker-desktop/\n\n[docker-image-base]: https://hub.docker.com/repository/docker/throwtheswitch/madsciencelab\n[docker-image-plugins]: https://hub.docker.com/repository/docker/throwtheswitch/madsciencelab-plugins\n[docker-image-arm]: https://hub.docker.com/repository/docker/throwtheswitch/madsciencelab-arm-none-eabi\n[docker-image-arm-plugins]: https://hub.docker.com/repository/docker/throwtheswitch/madsciencelab-arm-none-eabi-plugins\n\n### Example super-duper simple Ceedling configuration file\n\n```yaml\n:project:\n  :build_root: project/build/\n  :release_build: TRUE\n\n:paths:\n  :test:\n    - tests/**\n  :source:\n    - source/**\n  :include:\n    - inc/**\n```\n\nSee this [commented project configuration file][example-config-file] for a much more complete and sophisticated example of a project configuration.\n\nOr, use Ceedling’s built-in `examples` \u0026 `example` commands to extract a sample project and reference its project file.\n\nSee the [configuration section][ceedling-packet-config] in _Ceedling Packet_ for way more details on your project configuration options than we can provide here.\n\n[example-config-file]: assets/project.yml\n[ceedling-packet-config]: docs/CeedlingPacket.md#the-almighty-ceedling-project-configuration-file-in-glorious-yaml\n\n## Using Ceedling’s command line (and related)\n\n### Command line help\n\nFor an overview of all commands, it’s as easy as…\n\n```sh\n \u003e ceedling help\n```\n\nFor a detailed explanation of a single command…\n\n```sh\n \u003e ceedling help \u003ccommand\u003e\n```\n\n### Creating a project\n\nCreating a project with Ceedling is easy. Simply tell Ceedling the name of the\nproject, and it will create a directory with that name and fill it with a\ndefault subdirectory structure and configuration file. An optional destination\npath is also possible.\n\n```shell\n \u003e ceedling new YourNewProjectName\n```\n\nYou can add files to your `src/` and `test/` directories, and they will\ninstantly become part of your test and/or release build. Need a different \nstructure? You can modify the `project.yml` file with your new path or \ntooling setup.\n\n#### Installing local documentation\n\nAre you just getting started with Ceedling? Maybe you’d like your\nproject to be installed with some of its handy [documentation](docs/)? \nNo problem! You can do this when you create a new project…\n\n```shell\n \u003e ceedling new --docs MyAwesomeProject\n```\n\n#### Attaching a Ceedling version to your project\n\nCeedling can be installed as a globally available Ruby gem. Ceedling can \nalso deploy all its guts into your project instead. This allows it to \nbe used without worrying about external dependencies. More importantly, \nyou don’t have to worry about Ceedling changing outside of your project \njust because you updated your gems. No need to worry about changes in \nUnity or CMock breaking your build in the future.\n\nTo use Ceedling this way, tell it you want a local copy when you create\nyour project:\n\n```shell\n \u003e ceedling new --local YourNewProjectName\n```\n\nThis will install all of Unity, CMock, CException, and Ceedling itself \ninto a new folder `vendor/` inside your project `YourNewProjectName/`.\nIt will create the same simple empty directory structure for you with\n`src/` and `test/` folders as the standard `new` command.\n\n### Running build \u0026 plugin tasks\n\nYou can view all the build and plugin tasks available to you thanks to your\nCeedling project file with `ceedling help`. Ceedling’s command line help\nprovides a summary list from your project configuration if Ceedling is\nable to find your project file (`ceedling help help` for more on this).\n\nRunning Ceedling build tasks tends to look like this…\n\n```shell\n \u003e ceedling test:all release\n```\n\n```shell\n \u003e ceedling gcov:all --verbosity=obnoxious --test-case=boot --mixin=code_cruncher_toolchain\n```\n\n### Upgrading / updating Ceedling\n\nYou can upgrade to the latest version of Ceedling at any time, automatically\ngaining access to any accompanying updates to Unity, CMock, and CException.\n\nTo update a locally installed gem…\n\n```shell\n \u003e gem update ceedling\n```\n\nOtherwise, if you are using the Docker image, you may upgrade by pulling\na newer version of the image…\n\n```shell\n \u003e docker pull throwtheswitch/madsciencelab:\u003ctag\u003e\n```\n\nIf you want to force a vendored version of Ceedling inside your project to \nupgrade to match your latest gem, no problem. Just do the following…\n\n```shell\n \u003e ceedling upgrade --local YourNewProjectName\n```\n\nJust like with the `new` command, an `upgrade` should be executed from \nwithin the root directory of your project.\n\n### Git integration\n\nAre you using Git? You might want Ceedling to create a `.gitignore` \nthat ignores the build folder while retaining control of the artifacts\nfolder. This will also add a `.gitkeep` file to your `test/support` folder.\nYou can enable this by adding `--gitsupport` to your `new` call.\n\n```shell\n \u003e ceedling new --gitsupport YourNewProjectName\n```\n\u003cbr/\u003e\n\n# 💻 Contributing to Ceedling Development\n\n## Alternate installation options for Ceedling development\n\n### Alternate local installation for development\n\nAfter installing Ruby…\n\n```shell\n \u003e git clone --recursive https://github.com/throwtheswitch/ceedling.git\n \u003e cd ceedling\n \u003e git submodule update --init --recursive\n \u003e bundle install\n```\n\nThe Ceedling repository incorporates its supporting frameworks and some\nplugins via Git submodules. A simple clone may not pull in the latest\nand greatest.\n\nThe `bundle` tool ensures you have all needed Ruby gems installed. If \nBundler isn’t installed on your system or you run into problems, you \nmight have to install it:\n\n```shell\n \u003e sudo gem install bundler\n```\n\nIf you run into trouble running bundler and get messages like _can’t \nfind gem bundler (\u003e= 0.a) with executable bundle \n(Gem::GemNotFoundException)_, you may need to install a different \nversion of Bundler. For this please reference the version in the \nGemfile.lock.\n\n```shell\n \u003e sudo gem install bundler -v \u003cversion in Gemfile.lock\u003e\n```\n\n### Alternate Docker image usage for development\n\nAs an alternative to local installation of Ceedling, nearly all development \ntasks can be accomplished with the _MadScienceLab_ Docker images.\n\nWhen running an existing image as a development container, one merely needs \nto map a volume from your local Ceedling code repository to Ceedling’s \ninstallation location within the container. With that accomplished, \nexperimenting with project builds and running self-tests is simple.\n\n1. Start your target Docker container from your host system terminal:\n\n   ```shell\n   \u003e docker run -it --rm throwtheswitch/\u003cimage\u003e:\u003ctag\u003e\n   ```\n1. Look up and note Ceedling’s installation path (listed in `version` output) from within the container command line:\n\n   ```shell\n   ~/project \u003e ceedling version\n\n\n   ```\n1. Exit the container.\n1. Restart the container from your host system with the Ceedling installation\n   volume mapping from (2) and any other command line options you need:\n\n   ```shell\n   \u003e docker run -it --rm -v /my/local/ceedling/repo:\u003ccontainer installation path\u003e -v /my/local/experiment/path:/home/dev/project throwtheswitch/\u003cimage\u003e:\u003ctag\u003e\n   ```\n\nFor development tasks, from the container shell you can:\n\n1. Run experiment projects you map into the container (e.g. at _/home/dev/project_).\n1. Run the self-test suite. Navigate to the gem installation path discovered in (2) above. From this location, follow the instructions in the section that immediately follows.\n\n## Running Ceedling’s self-tests\n\nCeedling uses [RSpec] for its tests.\n\nTo execute tests you may run the following from the root of your local \nCeedling repository. This test suite build option balances test coverage\nwith suite execution time.\n\n```shell\n \u003e rake spec\n```\n\nTo run individual test files (Ceedling’s Ruby-based tests, that is) and \nperform other tasks, use the available Rake tasks. From the root of your \nlocal Ceedling repo, list those task like this:\n\n```shell\n \u003e rake -T\n```\n\n[RSpec]: https://rspec.info\n\n## Working in `bin/` vs. `lib/`\n\nMost of Ceedling’s functionality is contained in the application code residing \nin `lib/`. Ceedling’s command line handling, startup configuration, project\nfile loading, and mixin handling are contained in a “bootloader” in `bin/`.\nThe code in `bin/` is the source of the `ceedling` command line tool and \nlaunches the application from `lib/`.\n\nDepending on what you’re working on you may need to run Ceedling using\na specialized approach.\n\nIf you are only working in `lib/`, you can:\n\n1. Run Ceedling using the `ceedling` command line utility you already have \n   installed. The code in `bin/` will run from your locally installed gem or \n   from within your Docker container and launch the Ceedling application for \n   you.\n1. Modify a project file by setting a path value for `:project` ↳ `:which_ceedling` \n   that points to the local copy of Ceedling you cloned from the Git repository.\n   See _CeedlingPacket_ for details.\n\nIf you are working in `bin/`, running `ceedling` at the command line will not\ncall your modified code. Instead, you must execute the path to the executable\n`ceedling` in the `bin/` folder of the local Ceedling repository you are \nworking on.\n\n\n\n","funding_links":["https://github.com/sponsors/ThrowTheSwitch"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthrowtheswitch%2Fceedling","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthrowtheswitch%2Fceedling","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthrowtheswitch%2Fceedling/lists"}