{"id":"itsfrank/frktest","name":"frktest","scope":"itsfrank","platform":"roblox","description":"Simple testing framework","version":"0.0.2","latest":"0.0.2","versions":["0.0.1","0.0.2"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{},"integrity":"46114715545f88a9a1feb08d68338d2b4d9aab9c1fdb1bdaba17a58a31d1d9b4","likes":0,"downloads":0,"install":"forest install itsfrank/frktest","url":"https://forest.dev/p/roblox/itsfrank/frktest","files":"https://api.forest.dev/ai/package/roblox/itsfrank/frktest/files","readme":"# frktest\n\nA basic unit test framework for [lune](https://github.com/lune-org/lune).\n\nI developed this mostly for myself at a time where there were no alternatives\nfor Lune. I plan to keep it simple and use it for my projects that dont require\na heavy framework.\n\nIf you require more than basic test running, assertions, and console reporting,\nconsider using a larger framework (like\n[jest-lua](https://github.com/jsdotlua/jest-lua) when it gets ported to lune,\nsee [issue](https://github.com/jsdotlua/jest-lua/issues/2) for tracking)\n\n### Features\n\n- It runs tests\n- Pretty ergonomic to write (I think so)\n- Assertion library, including table & array checks with diff printing, should_error, and a few more!\n- Builtin console reporter with **colors**\n- (undocumented) api to implement custom reporters (see [lune_console_reporter.luau](src/reporters/lune_console_reporter.luau) for sample use)\n\n### What does it look like tho?\n\nHere's what a test looks like:\n\n```lua\nreturn function()\n    test.suite(\"A collection of tests\", function()\n        test.case(\"A test that passes\", function()\n            local exp = 4\n            local got = 2 + 2\n            check.equal(got, exp)\n        end)\n\n        test.case(\"A test that fails\", function()\n            local exp = 3\n            local got = 2 + 2\n            check.equal(got, exp)\n        end)\n\n        test.case(\"Halt early\", function()\n            local a = nil\n            req.not_nil(a)\n            check.falsy(a.b) -- wont run, a failed req stops the test early\n        end)\n\n        test.case(\"Custom messages!\", function()\n            check.equal(1, 2, msg(\"my message prints in addition to the expansion\"))\n        end)\n\n        test.case(\"Array assertions\", function()\n            local a = { \"a\", \"b\", \"c\" }\n            local b = { \"a\", \"z\" }\n            check.array.contains(a, { \"z\", \"x\" })\n            check.array.equal(a, b)\n        end)\n\n        test.case(\"Table assertions\", function()\n            local a = { a = 1, b = 2, c = { a = 1, b = 2 } }\n            local b = { a = 1, b = 22, c = { a = -1 } }\n            check.table.contains(a, \"b\")\n            check.table.equal(a, b)\n        end)\n    end)\n\n    -- you can use test.focus to temporarily focus on a test case/suite:\n    test.focus.suite(\"only this suite will run\", function() end)\n    test.focus.case(\"only this case will run\", function() end) \n\n    -- you can use test.skip to skip test cases/suites:\n    test.skip.suite(\"all tests in this suite will be skipped\", function() end)\n    test.skip.case(\"this test will be skipped\", function() end) \nend\n```\n\nAnd here is the output (theme is [Rose Pine](https://github.com/rose-pine)):\n\n![image](https://github.com/itsfrank/frktest/assets/7297152/f20a58d6-8e61-4635-893c-b4721ed9f3c9)\n\n### How do I use it\n\n#### Set up your environment\n\n**Installing**\n\nfrktest is available on [wally](https://wally.run/), [pesde](https://docs.pesde.daimond113.com/), or you can just clone the repo.\n\n<details>\n\n<summary>using wally</summary>\n\nAdd the dependency:\n\nin `wally.toml`:\n\n```toml\n[dev-dependencies]\nfrktest = \"itsfrank/frktest@0.0.2\"\n```\n\nCreate alias in `.luaurc`:\n\n```jsonc\n{\n  \"aliases\": {\n    \"frktest\": \"DevPackages/_Index/itsfrank_frktest@0.0.2/frktest/src\",\n  }\n}\n```\n\n</details>\n\n<details>\n\n<summary>using pesde</summary>\n\nin `pesde.toml`:\n\n```toml\n[dev_dependencies]\nfrktest = { name = \"itsfrank/frktest\", version = \"^0.0.2\" }\n```\n\nCreate alias in `.luaurc`:\n\n```jsonc\n{\n  \"aliases\": {\n    \"frktest\": \"lune_packages/.pesde/itsfrank+frktest/0.0.2/frktest/src/\"\n  }\n}\n```\n\n**Note**: If you want to use the generated luau file in `./lune_packages`, in\nthe examples, replace `require(\"@frktest/frktest\")` with\n`require(\"./lune_packages/frktest\")`. Reporters will be avilable in the\n`_reporters` member:\n\n```luau\n-- from project root\nlocal frktest = require(\"./lune_packages/frktest\")\nlocal lune_console_reporter = frktest._reporters.lune_console_reporter\n```\n\nA sample pesde project using frktest can be found here: https://github.com/itsfrank/frktest-pesde-sample\n\n</details>\n\n<details>\n\n<summary>clone the repo</summary>\n\n```shell\n# somewhere on your machine\ngit clone https://github.com/itsfrank/frktest.git\n```\n\nCreate alias in `.luaurc`:\n\n```jsonc\n{\n  \"aliases\": {\n    \"frktest\": \"<path to frktest/src>\",\n  }\n}\n```\n\n</details>\n\nAll example assume you created a `require` alias `\"@frktest\"` in your project's `.luaurc`:\n\n```jsonc\n{\n  \"aliases\": {\n    \"frktest\": \"<see install sections above for paths>\",\n  }\n}\n```\n\n**note:** you should also register the alias with your lsp of choice, with `luau-lsp` using VSCode I think it would look like this:\n\n```json\n\"luau-lsp.require.mode\": \"relativeToFile\",\n\"luau-lsp.require.directoryAliases\": {\n    \"@frktest/\": \"<alias in luaurc>\"\n}\n```\n\n#### Running tests\n\nThe framework does not have a cli or test discovery. So you need to make an entrypoint file, see [examples/_run.luau](examples/_run.luau) for how I made mine. But basically all you need is this:\n\n```lua\n-- filename: _run.luau\n\n-- require test files and call the returned function\nrequire(\"./some_test\")()\n\n-- initialize a reporter (there is currently only one... this one, but you can make your own!)\nlocal lune_console_reporter = require(\"@frktest/reporters/lune_console_reporter\")\nlune_console_reporter.init()\n\n-- run the tests\nlocal frktest = require(\"@frktest/frktest\")\nfrktest.run()\n```\n\nThen you can run this file with lune like so:\n\n```shell\n> lune run _run.luau\n```\n\n#### Writing tests\n\nI suggest you use these requires (but you do what you want!):\n\n```lua\nlocal frktest = require(\"@frktest/frktest\")\nlocal test = frktest.test\nlocal check = frktest.assert.check\nlocal req = frktest.assert.require\n```\n\nA test file should return a function, and for any tests to run the function\nneeds to create tests with `test.case`. If you want to group tests together you\ncan use `test.suite` and create tests inside of that. See [examples](examples)\nfor how I wrote a bunch of test files.\n\n```lua\nreturn function()\n    test.case(\"a global test\", function()\n        -- ...\n    end)\n\n    test.suite(\"a group of tests\", function()\n        test.case(\"a test within a suite\", function()\n            -- ...\n        end)\n    end)\nend\n```\n\n#### Assertions\n\nEvery single assertion has at least one example in the [examples](examples)\nfolder. If there are any nuances, I added comments.\n\nReally though, they should be self explanatory, your LSP should list them all\nout if you type `assert.check.|`\n\n### End stuff\n\n#### TODO\n\n- Write tests to test the framework (ironic...)\n- Encapsulate test state so that I can test the framework using the framework (with 2 separate states, one doing the testing, and one being tested)\n- Probably add more assertions\n- Fix bugs people might report\n\n#### Acknowledgements\n\n- [martinfelis/luatablediff](https://github.com/martinfelis/luatablediff) for a great table diff inplementation that I adapted for the `table.equal` assertions\n- [kikito/inspect](https://github.com/kikito/inspect.lua) because it's the best pretty printer and I use it to print tables\n- [catch2](https://github.com/catchorg/Catch2) inspired the test output and probably the assertion syntax\n\n#### What's up with the name?\n\nMy name is Frank, I often use `frk` as a namespace/prefix for stuff meant for me :)\n","readmeTruncated":false}