{"id":27311768,"url":"https://github.com/ditrit/specimen","last_synced_at":"2025-04-12T06:36:07.343Z","repository":{"id":57654279,"uuid":"452815223","full_name":"ditrit/specimen","owner":"ditrit","description":"A data-driven testing library as well as a yaml data format.","archived":false,"fork":false,"pushed_at":"2024-12-26T08:52:50.000Z","size":303,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-30T16:01:53.740Z","etag":null,"topics":["data-driven-testing","golang","js","python","rust","typescript","yaml"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ditrit.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-01-27T19:24:06.000Z","updated_at":"2024-12-26T08:52:54.000Z","dependencies_parsed_at":"2024-06-20T01:36:16.240Z","dependency_job_id":"f9e28460-9772-4a56-ac98-23dcbdb54837","html_url":"https://github.com/ditrit/specimen","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ditrit%2Fspecimen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ditrit%2Fspecimen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ditrit%2Fspecimen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ditrit%2Fspecimen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ditrit","download_url":"https://codeload.github.com/ditrit/specimen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247927311,"owners_count":21019506,"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":["data-driven-testing","golang","js","python","rust","typescript","yaml"],"created_at":"2025-04-12T06:36:01.140Z","updated_at":"2025-04-12T06:36:03.663Z","avatar_url":"https://github.com/ditrit.png","language":"Rust","readme":"# Specimen\n\n_Yaml-based data-driven testing_\n\nSpecimen is a data-driven testing library as well as a yaml data format. It enforces separation between the _feature being tested_ and the _data_ used for testing. Specimen enable the creation of language-agnostic actionable specifications.\n\nSo far, Specimen has been implemented in four languages: **Rust**, **Golang**, **Python** and **JS** (TypeScript acutally). The implementations are backed by the common [Specimen specification](spec).\n\nIt supports using the `FOCUS` and `PENDING` flags in the data tree to run only parts of the test data.\n\n## Overview\n\n![overview of the way the specimen library works](doc/specimen-overview.svg)\n\n- A **Test Box** is a user-defined function passed to `specimen.run`. It serves as an adaptator between Specimen and the user code being tested. As such, it prepares the data for testing, runs the code being tested and performs the checks on the code result once it has finished.\n- A **Slab** is a leaf of the yaml files data tree that Specimen processes.\n- A **Tile** is a chunk of data to be loaded into a test box. When test matrices are used, a slab will produce multiple tiles.\n\n## Getting started with Specimen in Golang\n\nTo get started, create a directory `it/` and the three files `it.go` `it_test.go` and `it_testdata.yaml`. For each file, copy the content of linked section. Install the dependencies and finally run `go test` in the `it/` directory:\n\n```sh\nmkdir it\ncd it\ntouch it.go it_test.go it_testdata.yaml\n```\n\nFill each of the three files with the code found in this README:\n\n- For `it.go` see [Example package code](#example-package-code)\n- For `it_test.go` see [Code box](#test-box)\n- For `it_testdata.yml` see [Yaml Data](#yaml-data)\n\nFinally, run:\n\n```sh\ngo mod init it\ngo mod tidy\ngo test\n```\n\nYou should get an output similar to this one:\n\n```\nTestIt:\nRan 4 tiles in 0s\nSUCCESS -- 4 Passed | 0 Failed | 0 Aborted | 0 Panicked\nPASS\nok      it      0.646s\n```\n\n`/!\\` If `go mod tidy` fails to find the specimen module, you may need to clean the go cache: `go clean -cache`, `go clean -modcache`.\n\n## Yaml Data\n\nThe yaml data file looks like this:\n\n```yaml\nbox: zoo\ncontent:\n  - content:\n      - name: horse\n        animal: horse\n        expected_result: horse\n      - flag: PENDING\n        name: parasprite # this slab will be ignored\n        animal: parasprite\n  - name: zebra\n    animal: zebra\n    expected_result: horse zebra\n  - name: animal matrix\n    animal: [mouse, cat, dog]\n  - name: matrix check\n    animal: wolf\n    expected_result: horse zebra mouse cat dog wolf\n```\n\n## Test box\n\nA test box is an **adapter** between the parsed data and the library code being tested. It takes as input the testing context `s` and the **input map**. A test box looks like this:\n\n```go\npackage it_test\n\nimport (\n\t\"testing\"\n\n\tspecimen \"github.com/ditrit/specimen/go\"\n\t\"github.com/ditrit/specimen/test/zoo\"\n)\n\n\nfunc TestIt(t *testing.T) {\n    specimen.Run(\n        t,\n        func(s *specimen.S, input specimen.Dict) {\n            animal := input[\"animal\"]\n            expected := input[\"expected_result\"]\n\n            if len(animal) \u003e 0 {\n                output := zoo.AddAnimal(animal)\n\n                if len(expected) \u003e 0 {\n                    s.ExpectEqual(output, expected, \"result comparison\")\n                }\n            }\n\t\t    },\n        []specimen.File{\n            specimen.ReadLocalFile(\"it_testdata.yaml\"),\n        },\n    )\n}\n```\n\n## Example package code\n\n```go\npackage it\n\nimport \"strings\"\n\ntype Zoo []string\n\nvar zoo Zoo\n\nfunc AddAnimal(animal string) string {\n\tzoo = append(zoo, animal)\n\treturn strings.Join(zoo, \" \")\n}\n```\n\n## Running the tests\n\n```sh\n# rust\ncd rust\ncargo test\n\n# golang\ngo test ./test/counter ./test/novel ./test/zoo\n# or\ngo test test/counter/counter_test.go\ngo test test/novel/novel_test.go\ngo test test/zoo/zoo_test.go\n\n# python (v3.10 or a future version)\ncd python\npython -m poetry install\ncd ..\n(cd test/counter \u0026\u0026 python counter_test.py)\n(cd test/novel \u0026\u0026 python novel_test.py)\n(cd test/zoo \u0026\u0026 python zoo_test.py)\n\n# js\ncd js\nyarn install\nyarn build\ncd ..\nnode test/counter/counter_test.js\n(cd test/novel \u0026\u0026 yarn install \u0026\u0026 node novel_test.js)\nnode test/zoo/zoo_test.js\n```\n\n## Yaml Schema\n\nThe content of a yaml test data file must match the `main` rule of the lidy schema below:\n\n```yaml\nmain: nodule\n\n# A tip can be a string or a list of strings. In the case of a list, all the\n# combination of values taken from this list and lists of other parameters will\n# be generated and run. This produces the effect of a test matrix.\ntip:\n  _oneOf:\n    - string\n    - _listOf: string\n\nnodule:\n  _mapFacultative:\n    # `content` contains all the children of the current nodule. Nodes which\n    # contain a content entry are seen as tree nodes, while nodes which do\n    # not contain it are seen as leaves\n    content:\n      - _listOf: nodule\n    # The flag can start with \"PENDING\" or \"FOCUS\" or not be specified.\n    # The PENDING flag tells the engine to skip the node and all its decendants.\n    # The FOCUS flag tells the engine to skip all the OTHER nodes; the one which\n    # do not have the flag \"FOCUS\".\n    flag: string\n    # `about` can contain any data: it will not be checked by the parser, and it\n    # will not appear in the data passed to the box function\n    about: any\n  # all the entries of the mapping will be added to the descendant slabs of\n  # this nodule and then passed to the code box, except for the `content`,\n  # `flag` and `about` entries\n  _mapOf: { string: tip }\n# Besides all the keys that are found in the yaml, the test box will be passed\n# an argument \"filepath\" which contains the path to the yaml file, as specified\n# to Lidy.\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fditrit%2Fspecimen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fditrit%2Fspecimen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fditrit%2Fspecimen/lists"}