{"id":43509938,"url":"https://github.com/getndazn/kopytko-unit-testing-framework","last_synced_at":"2026-02-03T12:49:23.707Z","repository":{"id":37710414,"uuid":"384134907","full_name":"getndazn/kopytko-unit-testing-framework","owner":"getndazn","description":"Extended Roku's Unit Testing Framework with additional assert functionalities and the mocking mechanism.","archived":false,"fork":false,"pushed_at":"2024-02-06T13:50:36.000Z","size":582,"stargazers_count":4,"open_issues_count":2,"forks_count":3,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-11-23T03:11:50.932Z","etag":null,"topics":["kopytko","roku","unit-testing"],"latest_commit_sha":null,"homepage":"","language":"Brightscript","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/getndazn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":"docs/ROADMAP.md","authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-08T13:32:39.000Z","updated_at":"2025-09-03T08:28:10.000Z","dependencies_parsed_at":"2023-12-05T10:26:43.272Z","dependency_job_id":"aae1063e-9207-4e5a-8375-1b938b6191d8","html_url":"https://github.com/getndazn/kopytko-unit-testing-framework","commit_stats":{"total_commits":67,"total_committers":12,"mean_commits":5.583333333333333,"dds":0.7164179104477613,"last_synced_commit":"c001e87ea85c0663b4e0313477f509b8ee160da4"},"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"purl":"pkg:github/getndazn/kopytko-unit-testing-framework","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getndazn%2Fkopytko-unit-testing-framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getndazn%2Fkopytko-unit-testing-framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getndazn%2Fkopytko-unit-testing-framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getndazn%2Fkopytko-unit-testing-framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/getndazn","download_url":"https://codeload.github.com/getndazn/kopytko-unit-testing-framework/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/getndazn%2Fkopytko-unit-testing-framework/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29046488,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-03T10:09:22.136Z","status":"ssl_error","status_checked_at":"2026-02-03T10:09:16.814Z","response_time":96,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["kopytko","roku","unit-testing"],"created_at":"2026-02-03T12:49:23.058Z","updated_at":"2026-02-03T12:49:23.699Z","avatar_url":"https://github.com/getndazn.png","language":"Brightscript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Kopytko Unit Testing Framework\n\n- [App Structure](#app-structure)\n- [Setup](#setup)\n- [Running Unit Tests](#running-unit-tests)\n- [Kopytko Unit Test Philosophy](#kopytko-unit-test-philosophy)\n- [Test Mocks](#test-mocks)\n- [Setup and Teardown](#setup-and-teardown)\n- [Limitations](#limitations)\n- [API](#api)\n- [Example test app config and unit tests](#example-test-app-config-and-unit-tests)\n- [Migration from v1 to v2](#migration-from-v1-to-v2)\n\nThe unit testing framework works on top of the [Roku Unit Testing framework](https://github.com/rokudev/unit-testing-framework). There are some differences between those two frameworks.\n\n## App Structure\n\nWe believe tests should be close to the tested objects.\n\nThe expected structure of the app:\n\n```\n components\n  _mocks\n    MyService.mock.brs\n  _tests\n    MyComponent.test.brs\n  MyComponent.brs\n  MyComponent.xml\n  MyService.brs\n```\n\nThe `_tests` folders should be placed near to the tested entity. Each test suite gains extra powers:\n\n- no need for xml files\n- no need to define test suites functions in an array\n- ability to import dependencies\n- ability to mock dependencies automatically\n- ability to mock dependencies manually\n\n## Setup\n\n1. Install framework as a dev dependency\n```shell\nnpm install @dazn/kopytko-unit-testing-framework --save-dev\n```\n\n2. Kopytko Unit Testing Framework uses [Kopytko Packager](https://github.com/getndazn/kopytko-packager) to build apps.\n   If you don't use it yet, go to its docs and init a @kopytko app. Once done, setup test environment in your `.kopytkorc` file\n```json\n{\n  \"pluginDefinitions\": {\n    \"generate-tests\": \"/node_modules/@dazn/kopytko-unit-testing-framework/plugins/generate-tests\"\n  },\n  \"plugins\": [\n    { \"name\": \"kopytko-copy-external-dependencies\", \"preEnvironmentPlugin\": true }\n  ],\n  \"environments\": {\n    \"test\": {\n      \"plugins\": [\"generate-tests\"]\n    }\n  }\n}\n```\nRemark: You can use any name for the test environment, just be consistent.\n\n3. Setup test script in your `package.json`\n```json\n{\n  \"scripts\": {\n    \"test\": \"ENV=test node ../scripts/test.js\"\n  }\n}\n```\n\n4. \\[Temporary\\] To not force [migration from v1 to v2](#migration-from-v1-to-v2) to be imidiate we introduced a bs_const flag (details in Migration part). The flag will be temporary for the depreciation period. In your manifest file please add bs_const:\n```js\n{\n  bs_const: {\n    insertKopytkoUnitTestSuiteArgument: false,\n  }\n}\n```\n\n## Running Unit Tests\n\nSimply\n```shell\nnpm test\n```\n\nIf you want to run unit tests of a specific unit, you can pass the file name as a default argument:\n```shell\nnpm test -- MyTestableUnit\n```\nThis is a shortcut for `npm test -- --testFileName=MyTestableUnit`\n\n## Kopytko Unit Test Philosophy\n\nThe unit tests can be split into multiple files and imported by the packager automatically. Let's consider the following example:\n```\n components\n  _tests\n    MyService_getData.test.brs\n    MyService_Main.test.brs\n    MyServiceTestSuite.test.brs\n  MyService.brs\n```\n`MyService.brs`\n```brightscript\nfunction MyService() as Object\n  prototype = {}\n\n  prototype.getData = function (arg as String) as Object\n    return { arg: arg }\n  end function\n\n  return prototype\nend function\n```\n`MyServiceTestSuite.test.brs`\n```brightscript\n' @import /components/KopytkoTestSuite.brs from @dazn/kopytko-unit-testing-framework\nfunction MyServiceTestSuite() as Object\n  ts = KopytkoTestSuite()\n\n  beforeAll(sub (_ts as Object)\n    ' do something\n  end sub)\n\n  return ts\nend function\n```\n`MyService_Main.test.brs`\n```brightscript\nfunction TestSuite__MyService_Main() as Object\n  ts = MyServiceTestSuite()\n  ts.name = \"MyService - Main\"\n\n  it(\"should create new instance of the service\", function (_ts as Object) as String\n    return expect(MyService()).toBeValid()\n  end function)\n\n  return ts\nend function\n```\n`MyService_getData.test.brs`\n```brightscript\nfunction TestSuite__MyService_getData() as Object\n  ts = MyServiceTestSuite()\n  ts.name = \"MyService - getData\"\n\n  it(\"should return some data\", function (_ts as Object) as String\n   ' Given\n    service = MyService()\n    expected = { arg: \"abc\" }\n\n    ' When\n    result = service.getData(\"abc\")\n\n    'Then\n    return expect(result).toEqual(expected)\n  end function)\n\n  return ts\nend function\n```\nSuch structure is understood and imported automatically by the packager.\n\nBehind the scenes Kopytko Unit Testing Framework replaces the source/Main.brs file to run unit tests.\nRoku's Unit Testing Framework core file is automatically imported by Kopytko Packager via ROPM.\n\n## Test Mocks\n\nDependencies may be mocked by using `@mock` annotation after dependencies import in the main test file:\n\n`' @mock pkg:/components/example/ExampleService.brs`\n\nType of dependency will be automatically recognized and proper function or object mock will be automatically generated on the fly (during the build process). There are 3 different types:\n- object that implements methods\n- function\n- node\n\nIn case that auto-generated mock doesn't suit our needs, manual mock may be created. It has to be created under `_mocks` directory located next to the mocked file. Manual mock file has to be named after the mocked element with `.mock.brs` postfix e.g. `GlobalNode.mock.brs` for the `GlobalNode.brs` element.\n\nIt's also possible to create a common config for the mock. To do so, a file named after the mocked element with `.config.brs` postfix has to be added in the `_mocks` directory. Such config will be automatically imported when a dependency is mocked by the `@mock` annotation.\n\nExample `ExampleService.brs`:\n```brightscript\nfunction ExampleService(dependency as Object) as Object\n  prototype = {}\n\n  prototype.getData = function (arg as String) as Object\n    return { someKey: \"someValue\" }\n  end function\n\n  return prototype\nend function\n```\n`ExampleService.mock.brs`:\n```brightscript\nfunction ExampleService(dependency as Object) as Object\n  return Mock({\n    testComponent: m,\n    name: \"ExampleService\",\n    methods: {\n      getData: function (arg as Object) as Object\n        return m.getDataMock(\"getData\", { arg: arg })\n      end function,\n    },\n  })\nend function\n```\n\nIn the unit tests the special field `__mocks` will be created and configuration can be added:\n```brightscript\nm.__mocks.exampleService = {\n  getData: {\n    returnValue: 1,\n  },\n}\n```\nThe service can be used like a regular object:\n```brightscript\n service = ExampleService(dependency)\n data = service.getData(\"/test\")\n```\n\nWhen dependency is mocked (`@mock`).\nYou can use our `mockFunction` to set returned value of the mocked function. For example.\n\n```brs\nit(\"should return mocked function value\", function (_ts as Object) as String\n  ' Given\n  expected = 123\n  mockFunction(\"functionName\").returnedValue(expected)\n\n  ' When\n  result = functionReturningFunctionNameResult()\n\n  'Then\n  return expect(result).toEqual(expected)\nend function)\n```\n\nOr you can check if mocked function was called properly\n\n```brs\nit(\"should call functionName once with argument a = 1\", function (_ts as Object) as String\n  ' When\n  result = functionReturningFunctionNameResult()\n\n  'Then\n  return [\n    expect(\"functionName\").toHaveBeenCalledTimes(1),\n    expect(\"functionName\").toHaveBeenCalledWith({ a: 1 }),\n  ]\nend function)\n```\n\n[Here](docs/api/KopytkoMockFunction.md) are listed all `mockFunction` methods.\n\nThere are also plenty of examples [here](/example/app/components/_tests/mockExamples.test.brs).\n\nCalls to the methods or constructor can be inspected:\n```brightscript\n? mockFunction(\"ExampleService.getData\").getCalls()[0].params.arg\n? mockFunction(\"ExampleService\").getConstructorCalls()[0].params.dependency\n```\n\n## Setup and Teardown\n\nRoku Unit Testing Framework provides the way to execute your custom code before/after every test suite.\nHowever, to give more flexibility, Kopytko Unit Testing Framework overwrites `setUp` and `tearDown` properties of a test suite, so you shouldn't use them. Instead, add your function via `beforeAll` or `afterAll` methods of `KopytkoTestSuite`.\n`KopytkoFrameworkTestSuite` already contains some additional code to prepare and clean a test suite from Kopytko ecosystem related stuff.\nNotice that if you have test cases of a unit split into few files, every file creates a separate test suite, therefore all `beforeAll` and `afterAll` callbacks will be executed once per a file.\n\n`KopytkoTestSuite` provides additional possibility to run custom code before/after every test suite via `setBeforeEach` and `setAfterEach`\nmethods.\n\nFunctions passed into all these methods and arrays should have just one `ts` argument which is a test suite.\n\n## Limitations\n - The Framework was not tested with the annotations\n\n## API\n\n- [KopytkoTestSuite](docs/api/KopytkoTestSuite.md)\n- [KopytkoFrameworkTestSuite](docs/api/KopytkoFrameworkTestSuite.md)\n- [KopytkoTestFunctions](docs/api/KopytkoTestFunctions.md)\n- [KopytkoExpect](docs/api/KopytkoExpect.md)\n- [KopytkoMockFunction](docs/api/KopytkoMockFunction.md)\n\n## Example test app config and unit tests\n\nGo to [/example](example) directory\n\n## Migration from v1 to v2\n\nVersion 2 introduces new shorthand functions and because of that, we were able to remove the test suite object argument from the test case function.\n\nNow if you want to get the `ts` (test suite) object, you can get it by calling the `ts()` function in a test case.\n\nIn order to not make trouble for projects that already use v1, we introduced a **bs_const** flag [**insertKopytkoUnitTestSuiteArgument**](/example/manifest.js). So if you **don't want to change the current test cases implementation** add it to your manifest with the value **set to true**.\n\nWhen you want to use our new shorthand methods and you **don't need a test suite object argument**, as you don't use it, **set this flag to false**.\n\n**IMPORTANT: This flag is only temporary and will be removed in the future.\nThe desired solution is to not use the test suite argument.**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetndazn%2Fkopytko-unit-testing-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgetndazn%2Fkopytko-unit-testing-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgetndazn%2Fkopytko-unit-testing-framework/lists"}