{"id":26502894,"url":"https://github.com/grassator/bdd-for-c","last_synced_at":"2025-03-20T18:36:17.740Z","repository":{"id":45790817,"uuid":"58265506","full_name":"grassator/bdd-for-c","owner":"grassator","description":"A simple BDD library for the C language","archived":false,"fork":false,"pushed_at":"2021-12-28T12:02:31.000Z","size":105,"stargazers_count":97,"open_issues_count":1,"forks_count":12,"subscribers_count":7,"default_branch":"master","last_synced_at":"2023-04-09T14:49:32.571Z","etag":null,"topics":["bdd","c","cpp","tdd","test","test-driven-development","test-framework","testing"],"latest_commit_sha":null,"homepage":"","language":"C","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/grassator.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-07T12:42:19.000Z","updated_at":"2023-03-31T03:04:39.000Z","dependencies_parsed_at":"2022-07-16T15:30:51.178Z","dependency_job_id":null,"html_url":"https://github.com/grassator/bdd-for-c","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fbdd-for-c","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fbdd-for-c/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fbdd-for-c/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/grassator%2Fbdd-for-c/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/grassator","download_url":"https://codeload.github.com/grassator/bdd-for-c/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244672301,"owners_count":20491346,"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":["bdd","c","cpp","tdd","test","test-driven-development","test-framework","testing"],"created_at":"2025-03-20T18:36:16.985Z","updated_at":"2025-03-20T18:36:17.725Z","avatar_url":"https://github.com/grassator.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"# bdd-for-c\n\nThe `bdd-for-c` library is a [BDD][bdd] test framework for the [C language][c].\n\n\n## Quick Start\n\nTo start, simply download the framework header file which can be easily done\nwith curl on Linux, MacOS, and BSD Unix:\n\n```bash\ncurl -O https://raw.githubusercontent.com/grassator/bdd-for-c/master/bdd-for-c.h\n```\n\nNext, create a spec file, named something appropriate like `strncmp_spec.c` if\ntesting the `strncmp` function.  Add some tests and include the framework\nheader, like the following:\n\n```c\n#include \u003cstring.h\u003e\n#include \"bdd-for-c.h\"\n\nspec(\"strncmp\") {\n    static const char *test_string = \"foo\";\n\n    it(\"should return 0 when strings are equal\") {\n        check(strncmp(test_string, test_string, 12) == 0);\n        check(strncmp(test_string, \"foo\", 12) == 0);\n    }\n\n    it(\"should work for empty strings\") {\n        check(strncmp(\"\", \"\", 12) == 0);\n    }\n\n    it(\"should return non-0 when strings are not equal\") {\n        check(strncmp(\"foo\", \"bar\", 12) != 0);\n        check(strncmp(\"foo\", \"foobar\", 12) != 0);\n    }\n\n    it(\"should return 0 when strings match up to specified length\") {\n        check(strncmp(\"foobar\", \"foobaz\", 3) == 0);\n    }\n}\n```\n\nAssuming you have a C compiler like [Clang][clang] or [GCC][gcc] set up and\nready to go, just type in the following commands to compile and run the test:\n\n```bash\ncc strncmp_spec.c -o strncmp_spec\n./strncmp_spec\n```\n\nYou should then see test output similar to the following:\n\n```\nstrncmp\n  should return 0 when strings are equal (OK)\n  should work for empty strings (OK)\n  should return non-0 when strings are not equal (OK)\n  should return 0 when strings match up to specified length (OK)\n```\n\n\n## Dependencies\n\nOn *nix systems, bdd-for-c depends on the following libraries:\n\n* libncurses 5.x\n* libbsd\n\nOn Ubuntu-like (Debian) distributions you can install them via:\n\n```bash\nsudo apt-get install libncurses5-dev libbsd-dev\n```\n\n\n## Project Motivation and Development Philosophy\n\nIn order for testing to be truly useful, it needs to be easy to set up and use,\nbut also scalable for large projects.  The tests should be very readable but,\nideally, have the same look-and-feel as the host language.  The framework's\ntest output should be easy to read for both humans and machines.  Finally, if\nit's C, the framework should only rely on ANSI/ISO-C99 features.\n\nUnfortunately, all of the existing frameworks inspected before starting this\nproject lack one or more of those requirements, with the most common problem\nbeing BASIC-style `BEGIN` / `END` delimiters for a test, like in the [CSpec\nframework][cspec].  The issue with `BEGIN` / `END` delimiters is not just that\nit \"doesn't look like C\", but also that it imposes a different typing flow and\nscrews up auto-completion support for IDEs and programming text editors.\n\nThe bdd-for-c framework currently exclusively targets the model of \"one spec,\none executable\", as this model provides the fastest compile times (given a\ncorrectly structured project).  This also makes mocking much easier.\n\n\n## Handling State and Fixtures\n\nIf you need to set up some state once before all the tests, or before each of\nthe tests, `bdd-for-c` supports special `before` and `before_each` statements,\nand their counterparts `after` and `after_each`.  As a bonus, you can define as\nmany `before`, `after`, `before_each` and `after_each` statements in any order\nas you want, as long as they are on the same level as the corresponding `it`\nstatement.\n\n\u003e The only caveat with handling state is that, if you want to create some\n\u003e test-local variables, you need to mark them as `static`.  Otherwise, the\n\u003e changes done `before` and `before_each` will not persist to the test itself,\n\u003e as each of the tests and these setup / teardown functions are implemented as\n\u003e separate function calls.\n\nHere's how it all fits together:\n\n```c\n#include \u003cstdio.h\u003e\n#include \"bdd-for-c.h\"\n\nspec(\"some feature\") {\n\n    static int test_count;\n    static int tests_failed;\n\n    after() {\n        printf(\"  All done!\\n\");\n    }\n\n    after() {\n        printf(\"%i tests run. %i failed.\\n\", test_count, tests_failed);\n    }\n\n    before() {\n        test_count = 0;\n        tests_failed = 0;\n    }\n\n    before() {\n        printf(\"  Starting the tests...\\n\\n\");\n    }\n\n    before_each() {\n        ++test_count;\n        ++tests_failed;\n    }\n\n    after_each() {\n        --tests_failed;\n    }\n\n    describe(\"broken math\") {\n        it(\"should not be equal\") {\n            check(3 + 2 != 6, \"this is indeed broken!\");\n        }\n    }\n\n    context(\"when everything is right\") {\n        it(\"should work\") {\n            check(3 + 3 == 6);\n        }\n    }\n}\n```\n\n\n## Output Colorization\n\nBy default, if the terminal correctly reports its color printing ability and\nthe application is run in the interactive mode (from terminal), then the output\nis going to be colorized.\n\nTo disable this mode, simply add a define statement before you include the\n`bdd-for-c.h` file:\n\n```c\n#define BDD_USE_COLOR 0\n#include \"bdd-for-c.h\"\n```\n\n\u003e Note to [CLion][clion] users: To get colored output when running tests from\n\u003e the IDE, you need to add `TERM=xterm-256color` to the `Environment Variables`\n\u003e field of your build configuration.\n\n\n## Support for [TAP][tap]\n\nThe `bdd-for-c` library supports the [test anything protocol][tap], or TAP,\nwhich formats output to be easily readable by programs.  This allows easier\nintegration with continuous integration systems as well as the aggregation of\noutput from multiple executables that use `bdd-for-c`.\n\nTo switch to TAP output mode you can add a `define` statement before including\nthe framework:\n\n```c\n#define BDD_USE_TAP 1\n#include \"bdd-for-c.h\"\n```\n\nYou may also add an environment variable when you run a test, instead:\n\n```bash\nBDD_USE_TAP=1 ./strncmp_spec\n```\n\n\n## Available Statements\n\nThe `bdd-for-c` framework uses macros to introduce several new statements to\nthe C language that are similar to the built-in statements, such as `if`.\n\nThese macros are implemented to be syntactically identical to the built-in\nstatements.  Among other things, this means that for the statements that expect\na body, the body can be empty (by terminating it with a semicolon), contain one\nstatement, or contain a code block (a list of statements):\n\n```c\n#include \"bdd-for-c.h\"\n\nspec('statements') {\n    it(\"should not do anything\");\n    it(\"should be in short form\") check(1 + 1 == 2);\n    it(\"should have a code block\") {\n        check(1 + 1 == 2);\n    }\n}\n```\n\nAs with the built-in statements, you have to maintain a certain structure,\ndescribed where appropriate in the subsections below.\n\n### spec\n\nThe `spec` statement must be a top-level statement and there must be exactly\none `spec` statement in the test executable.  Using more than one will result\nin a compilation error.\n\nUse `spec(\"some functionality\")` to group a set of expectations and\nsetup/teardown code together, and to give the unit a name (in this case \"some\nfunctionality\").  This will be used for test reporting.\n\n### it\n\nYou must include `it` statements directly inside a `spec`, `describe`, or\n`context` statement.  Each `it` statement expects a string argument, typically\nstarting with \"should\", used as a human readable explanation for the test, and\nused in reporting: `it(\"should behave in some manner\")`.\n\nThe `it` statement is a basic structural block of the spec and is used to\nensure a particular expectation, validated using `check` statements (described\nbelow).\n\n### fit / it_only\n\nThis is is similar to `it`, but switches test runner into a mode where it\nwill only run tests defined with `fit` / `it_only`.\n\n### xit / it_skip\n\nThis is is similar to `it`, but skips this particular test. Unlike source\nediting options of disabling the tests like commenting out or `if (0)`\nyou still get in an entry in the output with the name of the test marked\nas `(SKIP)`.\n\n### describe\n\nA `describe` statement must be included directly inside a `spec` or `context`\nstatement, or within another `describe` statement.  It is used to group `it`\nstatements together, usually based on the fact that they belong to the same\nunit of program functionality.\n\n### context\n\nA `context` statement is functionally identical to `describe`, and should be\nused when it better conveys the topic of a group of tests.  It is usually used\nto group `describe` statements based on the fact they depend on the same\nprogram state, providing a way to easily set up the same program state for\nseveral test conditions.\n\n\u003e NOTE: Because `context` is a quite common global variable in C applications,\n\u003e it is possible to not expose the `context` implementation in `bdd-for-c` by\n\u003e setting a flag before including the `bdd-for-c` library:\n\n```c\n#define BDD_NO_CONTEXT_KEYWORD 1\n#include \"bdd-for-c.h\"\n```\n\n### check\n\nA `check` statement is used to check \"truthfulness\" of a given expression.  In\ncase of failure, it terminates the current spec block and reports an error.\nThese statements must be placed inside of `it` statements, either as direct or\nindirect children:\n\n```c\n#include \"bdd-for-c.h\"\n\nspec(\"natural number\") {\n    it(\"should be non-negative\") {\n        for (int i = 0; i \u003c 10; ++i) {\n            check(i \u003e 0);\n        }\n    }\n}\n```\n\nBy default, a `check` statement uses the provided expression for error\nreporting, so, if you run the code above, you will see the following line:\n\n```\nCheck failed: i \u003e 0\n```\n\nDepending on your variable naming, as in this example, test output can be\nunhelpful for figuring out the cause of the failure.  To remedy this problem,\nyou can provide a formatter and additional parameters in the same manner as\nwith `printf`:\n\n```\ncheck(i \u003e 0, \"a natural number %i must be greater than 0\", i);\n```\n\nThis can provide much more informative output:\n\n```\nCheck failed: a natural number 0 must be greater than 0\n```\n\n\u003e Due to limitations in the current implementation, the number of parameters to\n\u003e `check` is limited to 10.\n\nWhile `check` statements are mostly useful inside of `it` statements, you can\nuse them in setup and teardown statements (`before`, `after`, `before_each`,\n`after_each`) to validate some pre- or post-conditions as well.\n\n\n### before\n\nA `before` statement, if needed, can be included directly inside a `spec`,\n`describe`, or `context` statement.  It runs once before all of the `it`\nstatements in the group/spec and can be useful to set up some state.  You can\nuse as many `before` statements as necessary.\n\n\n### after\n\nAn `after` statement, if needed, can be included directly inside a `spec`,\n`describe`, or `context` statement.  It runs once after all `it` statements in\nthe group and can be useful to tear down some state.  You can use as many\n`after` statements as necessary.\n\n\n### before_each\n\nA `before_each` statement, if needed, can be included directly inside a `spec`,\n`describe`, or `context` statement.  It runs before each `it` statement and can\nbe useful to set up some state.  You can use as many `before_each` statements\nas necessary.\n\n\n### after_each\n\nAn `after_each` statement, if needed, can be included directly inside a `spec`,\n`describe`, or `context` statement.  It runs after each `it` statement and can\nbe useful to tear down some state.  You can use as many `after_each` statements\nas necessary.\n\n\n## License\n\nThe MIT License (MIT)\n\nCopyright (c) 2016 Dmitriy Kubyshkin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n\n\n[bdd]: https://en.wikipedia.org/wiki/Behavior-driven_development\n[c]: https://en.wikipedia.org/wiki/C_%28programming_language%29\n[clang]: http://clang.llvm.org\n[gcc]: http://clang.llvm.org\n[cspec]: https://github.com/arnaudbrejeon/cspec/wiki\n[clion]: https://www.jetbrains.com/clion/\n[tap]: https://testanything.org\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrassator%2Fbdd-for-c","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgrassator%2Fbdd-for-c","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgrassator%2Fbdd-for-c/lists"}