{"id":15355737,"url":"https://github.com/minivera/testifyjs","last_synced_at":"2026-01-07T06:12:29.320Z","repository":{"id":46508707,"uuid":"325868405","full_name":"Minivera/testifyjs","owner":"Minivera","description":"Declarative test framework for JavaScript inspired by the modern testing standards, without any magic","archived":false,"fork":false,"pushed_at":"2023-10-02T14:54:12.000Z","size":306,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-18T04:59:46.470Z","etag":null,"topics":["hacktoberfest","javascript","testing","testing-framework","testing-library","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/Minivera.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2020-12-31T20:24:07.000Z","updated_at":"2023-09-27T14:48:19.000Z","dependencies_parsed_at":"2022-07-19T22:33:49.967Z","dependency_job_id":"2f7f555d-5227-4128-9283-fedae8a12939","html_url":"https://github.com/Minivera/testifyjs","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Minivera%2Ftestifyjs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Minivera%2Ftestifyjs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Minivera%2Ftestifyjs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Minivera%2Ftestifyjs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Minivera","download_url":"https://codeload.github.com/Minivera/testifyjs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245908968,"owners_count":20692200,"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":["hacktoberfest","javascript","testing","testing-framework","testing-library","typescript"],"created_at":"2024-10-01T12:25:23.945Z","updated_at":"2026-01-07T06:12:29.270Z","avatar_url":"https://github.com/Minivera.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Testifyjs\n[![codecov](https://codecov.io/gh/Minivera/testifyjs/graph/badge.svg?token=A9UVKHB3LL)](https://codecov.io/gh/Minivera/testifyjs)\n![Pull Request validation](https://github.com/Minivera/testifyjs/workflows/Pull%20Request%20validation/badge.svg)\n\nTestify is a unit-testing framework for JavaScript and TypeScript providing and recognizable experience, but with added\nsimplicity, clarity, and reusability. Written in TypeScript, Testify can be integrated in any project without having\nto learn a separate CLI and configuration system. Just load testify and execute your script with node!\n\n## Why another testing framework?\nI was relatively unhappy with how much magic and configuration goes into the average testing framework. I wanted\nto experiment with a framework where I can focus on writing simple and reusable code without any headaches. A test\nframework should not a challenge to use, understand, or implement, I wanted to know if an alternative was possible.\n\nAnother major difficulty I have with testing framework is the lack of a traditional unit test structure. It leads\nto big tests where it gets hard to find where the data is set, where the test is executed, and where the data is\nchecked. I've always been a fan of the [Arrange-Act-Assert](https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/) \nstructure for unit tests, and I wanted to see if a framework would be built around this standard.\n\nTestify is not an attempt at revolutionizing the way people write tests in JavaScript, nor is it a \u003cinsert test\nframework here\u003e killer. It's a small project I designed to answer the above questions. I hope you will enjoy trying\nout testify for yourself and seeing if it helps you write better tests.\n\n## Why use Testify?\n\n* Very small library and API\n* Built with TypeScript, for TypeScript\n* Asynchronous support out of the box\n* Support for test suites\n* No magic or global injected variables, everything is imported or provided\n* Bring your own assertion framework or mocking library\n* All tests are sequential\n* Encourages writing small testing helpers over massive test methods (Arrange-Act-Assert)\n* No CLI, bring your own node and run testify with your configuration\n\n## How to use\n\nTo get started, install testify using NPM\n\n```\nnpm install @minivera/testifyjs\n```\n\nCreate a main test file somewhere in your code base, import testify, and run it.\n\n```js\nimport { testify, test } from '@minivera/testifyjs';\n\n// Create a single test\ntest('Hello, World!', test =\u003e {\n  test\n    // Arrange your data before acting\n    .arrange(() =\u003e ({\n      message: '',\n    }))\n    // Update the data based on what you are testing\n    .act(({ message }) =\u003e ({\n      message: 'Hello, World!'\n    }))\n    // Assert that the actions executed properly\n    .assert(({ message }) =\u003e {\n      if (message !== 'Hello, World!') {\n        throw new Error('Message should be \"Hello, World!\"');\n      }\n    });\n});\n\n// Run all the tests in the order they were created\nawait testify();\n```\n\nExecute this script with node and let testify take over.\n\n```bash\nnode test.js\n```\n\n### TypeScript support\nTestify was built in TypeScript, for TypeScript. Here is the same example, but built in TypeScript.\n\n```typescript\nimport { testify, test } from '@minivera/testifyjs';\n\ntest('Hello, World!', test =\u003e {\n  interface Input {\n    message: string;\n  }\n    \n  test\n    // First generic is the type of the parameter, second is the return type\n    .arrange\u003c{}, Input\u003e(() =\u003e ({\n      message: '',\n    }))\n    .act\u003cInput\u003e(({ message }) =\u003e ({\n      message: 'Hello, World!'\n    }))\n    .assert\u003cInput\u003e(({ message }) =\u003e {\n      if (message !== 'Hello, World!') {\n        throw new Error('Message should be \"Hello, World!\"');\n      }\n    });\n});\n\nawait testify();\n```\n\nAll the type definitions are available directly form the main `testify` import.\n\n### Asynchronous code\nAsync methods are supported by default, simply create a function returning a promise or an async function, and testify\nwill make sure to execute the code synchronously.\n\n```typescript\nimport { testify, test } from '@minivera/testifyjs';\n\nconst someApiCall = async (body: string) =\u003e {\n  return await fetch('somewhere', body);  \n};\n\n\ntest('async test', test =\u003e {\n  interface Input {\n    body: string;\n  }\n  \n  interface Output {\n    body: string;\n    result: string;\n  }\n    \n  test\n    .arrange\u003c{}, Input\u003e(() =\u003e ({\n      body: JSON.stringify({}),\n    }))\n    .act\u003cInput, Output\u003e(async ({ body }) =\u003e {\n        const result = await someApiCall(body);\n        return {\n            body,\n            result,\n        };\n    })\n    .assert\u003cOutput\u003e(({ result }) =\u003e {\n      if (result !== 'Hello, World!') {\n        throw new Error('Message should be \"Hello, World!\"');\n      }\n    });\n});\n\nawait testify();\n```\n\n### Triggering a test failure\nAt any point in you tests, you may throw an error to trigger a test failure. Testify will gracefully report the error\nand report the test failure.\n\n\n```typescript\nimport { testify, test } from '@minivera/testifyjs';\n\ntest('failing test', test =\u003e {\n  const triggerError = () =\u003e {\n      throw new Error('test');\n  };\n    \n  test\n    .arrange(triggerError)\n    .act(triggerError) // Will never be executed\n    .assert(triggerError); // Will never be executed\n});\n\nawait testify();\n```\n\n### Using suites\nTestify supports test suites to better organize tests or trigger specific behavior before and after tests.\n\n```typescript\nimport { testify, suite } from '@minivera/testifyjs';\n\nsuite('test suite', suite =\u003e {\n  suite.setup(() =\u003e {\n    // Will be executed when the suite starts, may be async\n  });\n  \n  suite.tearDown(() =\u003e {\n    // Will be executed when the suite ends, may be async\n  });\n  \n  suite.beforeEach(() =\u003e {\n    // Will be executed before every test or nested test suite, may be async\n  });\n\n  suite.afterEach(() =\u003e {\n    // Will be executed after every test or nested test suite, may be async\n  });\n    \n  // Can run individual test, they will be printed as part of the suite\n  suite.test('test', test =\u003e {\n    test\n      .arrange(someArrange)\n      .act(someAct)\n      .assert(someAssert);\n  });\n\n  // Suites can be freely nested\n  suite.suite('nested', suite =\u003e {\n    // ...\n  });\n});\n\nawait testify();\n```\n\n### Tests in multiple files\n`testify` will execute all registered tests at the moment it's run. You can divide your tests into multiple files\nby using the node module system. Make sure to call `testify` **after** you import all your tests.\n\n```typescript\n// somefile.ts\nimport { test } from '@minivera/testifyjs';\n\ntest('some test', () =\u003e { /* ... */ });\n\n// test.ts\nimport './somefile';\n\nawait testify();\n```\n\n## API\n\n### The test function\n\u003e `import { test } from '@minivera/testifyjs';`\n\n`test` takes two arguments, a name to be displayed when executing the test, and a test configuration function. The\nfunction receives the test object as its only parameter.\n\n### The suite function\n\u003e `import { suite } from '@minivera/testifyjs';`\n\n`suite` takes two arguments, a name to be displayed when executing the suite's test, and a suite configuration function. \nThe function receives the suite object as its only parameter.\n\n\n### The testify function\n\u003e `import { testify } from '@minivera/testifyjs';`\n\n`testify` executes all the tests saved up to this point.\n\n### The Test object\n\u003e `test('name', test =\u003e { /* test is your test object */});`\n\nThe test object is used to configure a single test. By itself, the test configuration function does nothing, we\nneed to provide it with test units.\n\n`test.arrange` takes a function as its parameter. This function will have the return value from the previous function\nin the chain as its parameter. A function may not return anything, in which case the return value from the previous\nchain is used as the return value. The first function receives an empty object as its parameter.\n\nIn TypeScript, the two generic parameters can be used to add type definitions to the input parameters and the output\nvalue. The second generic can be omitted, it will use the first value by default.\n\nFor example:\n\n```typescript\nimport { test } from '@minivera/testifyjs';\n\ntest('some test', test =\u003e {\n  interface A {\n    test: number;\n  }\n\n  interface B {\n    test: string;\n  }\n    \n  test.arrange\u003c{}, A\u003e(params =\u003e {\n    // params is {}\n    return {\n      test: 1,\n    };\n  }).arrange\u003cA\u003e(params =\u003e {\n    // params is { test: 1 }\n  }).arrange\u003cA, B\u003e(params =\u003e {\n    // params is still { test: 1 }\n    return {\n      test: `${params.test}`,\n    }\n  })\n});\n```\n\n`arrange`, `act`, and `assert` may be called as a chain to continue configuring this single test. `and` is also\navailable as syntactic sugar to call `arrange` multiple times.\n\n`test.act` is identical to `test.arrange`, with the difference that only `act` and `assert` are available for chaining\n`and` is still available as syntactic sugar to call `act` multiple times.\n\n`test.act` is identical to `test.act`, with the difference that only `assert` is available for chaining\n`and` is still available as syntactic sugar to call `assert` multiple times.\n\nAll functions provided to `arrange`, `act`, and `assert` may be async or return a promise. All steps will be executed\nsequentially and async methods will be `await`-ed.\n\n### The Suite object\n\u003e `suite('name', suite =\u003e { /* suite is your suite object */});`\n\nThe suite object is used to configure a test suite. The suite function does nothing if the suite is not configured\nby calling its methods. It also provides hooks to prepare data before or after the execution of the suites or individual\ntests.\n\nThe `suite.setup` hook takes a function as its single parameter and will set that function to be executed before the suite\nis executed proper. The function may be called multiple times to add a sequence of setup functions.\n\nThe `suite.tearDown` hook takes a function as its single parameter and will set that function to be executed after the suite\nhas been executed. The function may be called multiple times to add a sequence of teardown functions.\n\nThe `suite.beforeEach` hook takes a function as its single parameter and will set that function to be executed before every test\nor nested suite executes. The function may be called multiple times to add a sequence of functions.\n\nThe `suite.afterEach` hook takes a function as its single parameter and will set that function to be executed after every test\nor nested suite executes. The function may be called multiple times to add a sequence of functions.\n\n`suite.test` function like the `test` function with the exception that this test will be executed as part of the\nsuite.\n\n`suite.suite` function like the `suite` function with the exception that this test will be executed as part of the\nsuite. Suites can be nested indefinitely. Hooks of a nest suite will not conflict with the hooks of its parents.\n\n## Inspiration\n\n* [Ava](https://github.com/avajs/ava)\n* [jest](https://jestjs.io/)\n* [Golang testing](https://golang.org/pkg/testing/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminivera%2Ftestifyjs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fminivera%2Ftestifyjs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fminivera%2Ftestifyjs/lists"}