{"id":15494276,"url":"https://github.com/andyglow/scalacheck-gen-configured","last_synced_at":"2026-03-16T22:33:02.425Z","repository":{"id":50218140,"uuid":"184489859","full_name":"andyglow/scalacheck-gen-configured","owner":"andyglow","description":"Scalacheck's `Gen[T]` flexible configurator","archived":false,"fork":false,"pushed_at":"2025-03-17T14:07:39.000Z","size":179,"stargazers_count":1,"open_issues_count":3,"forks_count":1,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-29T18:36:29.251Z","etag":null,"topics":["environment-variables","scala","scalacheck","scalacheck-configurator","scalacheck-gen","scalacheck-generators"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/andyglow.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":"2019-05-01T22:28:42.000Z","updated_at":"2025-03-17T14:07:43.000Z","dependencies_parsed_at":"2023-09-28T04:08:33.583Z","dependency_job_id":"a5649c50-ef26-4ab9-9318-5a88c04eccbb","html_url":"https://github.com/andyglow/scalacheck-gen-configured","commit_stats":{"total_commits":125,"total_committers":5,"mean_commits":25.0,"dds":0.6639999999999999,"last_synced_commit":"eaab290621434965ea6d26411be7a80fcfb5a0e2"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andyglow%2Fscalacheck-gen-configured","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andyglow%2Fscalacheck-gen-configured/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andyglow%2Fscalacheck-gen-configured/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/andyglow%2Fscalacheck-gen-configured/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/andyglow","download_url":"https://codeload.github.com/andyglow/scalacheck-gen-configured/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250316614,"owners_count":21410577,"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":["environment-variables","scala","scalacheck","scalacheck-configurator","scalacheck-gen","scalacheck-generators"],"created_at":"2024-10-02T08:13:00.862Z","updated_at":"2026-03-16T22:33:02.399Z","avatar_url":"https://github.com/andyglow.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scalacheck `Gen[T]` configurator\n\n[![Build Status](https://github.com/andyglow/scalacheck-gen-configured/actions/workflows/ci.yml/badge.svg)]()\n[![codecov](https://codecov.io/gh/andyglow/scalacheck-gen-configured/branch/master/graph/badge.svg?token=LRRSC6V0RE)](https://codecov.io/gh/andyglow/scalacheck-gen-configured)\n[![mvn](https://img.shields.io/badge/dynamic/json.svg?label=mvn\u0026query=%24.response.docs%5B0%5D.latestVersion\u0026url=https%3A%2F%2Fsearch.maven.org%2Fsolrsearch%2Fselect%3Fq%3Dscalacheck-gen-configured_2.13%26start%3D0%26rows%3D1)](https://search.maven.org/artifact/com.github.andyglow/scalacheck-gen-configured_2.13/)\n\nWith this project you can externalize `Gen[T]` configuration. \n\nWhen I needed to generate some amount of test data the first think appeared to my mind was to use `Gen[T]` \nfrom awesome `scalacheck` project. I have written first version of data generator really quickly. I have deployed then\ninto right place, started, checked my app started receiving test data. That was cool. \n\nLet me show you the example.\n\n```scala\nimport java.time._\nimport org.scalacheck._\n\ncase class MyEvent(id: String, timeStamp: Instant, message: String)\n\nval myEventGen = for {\n  id        \u003c- Gen.identifier\n  timeStamp \u003c- Gen.choose(0, Instant.now().toEpochMilli) map { Instant.ofEpochMilli }\n  message   \u003c- Gen.alphaNumStr\n} yield MyEvent(id, timeStamp, message)\n```       \nThe code above is pretty much what I have started with.\nBut then I realized that I need to change test data generation profile. I needed to replace some `Gen.const` with, \nsay, `Gen.oneof` or `Gen.choose`. So, the only solution was to change the code and redeploy, restart, etc..\n\nThat is what always makes me unhappy.\n \nSo I thought, that would be helpful if I could change test data generation profile without real code change. \nCan we, for example, utilize environment variables to read generator definition from there?\nIn particular, can we do something like this\n```scala\ndef genFor[T](name: String): Option[Gen[T]] = {\n  sys.props.get(name) flatMap {\n    ParseGen(_).fold(\n      { err =\u003e log.warning(err); None },\n      { gen =\u003e Some(gen) })\n  }\n}\n    \nval myEventGen = for {\n  id        \u003c- genFor[String] (\"identifier\") getOrElse Gen.identifier\n  timeStamp \u003c- genFor[Instant](\"time-stamp\") getOrElse Gen.choose(0, Instant.now().toEpochMilli) map { Instant.ofEpochMilli }\n  message   \u003c- genFor[String] (\"message\")    getOrElse Gen.alphaNumStr\n} yield MyEvent(id, timeStamp, message)\n```   \n\nWith this solution the only thing I need is to restart data generation with desired system properties set. \n(`-Didentifier=alphaNumStr -Dtime-stamp=\"range: 2018-04-04T00:00Z .. 2018-04-14T23:59Z\"`) \n\nThe project is in it's initial phase so do not expect too much form it yet please.\n\nThe only pretty strict amount of type supported yet.\n- Most of scala numeric types (`Byte`, `Short`, `Int`, `Long`, `Float`, `Double`)\n- `Char` and `String`\n- `Boolean`\n- Date time types \n    - `java.time.Instant`\n    - `java.time.LocalDateTime`\n    - `java.time.LocalDate`\n    - `java.time.LocalTime`\n    - `java.time.OffsetDateTime`\n    - `java.time.ZonedDateTime`\n    - `java.util.Date`\n    - `java.util.Calendar`\n    - `java.sql.Date`\n    - `java.sql.Time`\n- Duration types\n    - `FiniteDuration`\n    - `Duration`\n\n## API\n`ParseGen[T](defn: String): Either[String, Gen[T]]`\n\nExamples\n```scala\nimport com.github.andyglow.scalacheck._\n\nval Right(idGen)        = ParseGen[String](\"identifier: 16\")\nval Right(posLongGen)   = ParseGen[Long](\"posNum\")\nval Right(timestampGen) = ParseGen[java.time.Instant](\"range: 2018-01-01T00:00Z .. 2018-12-31T23:59Z\")\n```\n    \n## Definitions\nBelow is a table showing which definitions can be supported by types.  \n\n|                      | Numeric types | Char | String | Boolean | Date types | Duration |\n| -------------------- | ------------- | ---- | ------ | ------- | ---------- | -------- |\n| `identifier`         |               |      | [x]    |         |            |          |\n| `numChar`            |               | [x]  |        |         |            |          |\n| `numStr`             |               |      | [x]    |         |            |          |\n| `alphaUpperChar`     |               | [x]  |        |         |            |          |\n| `alphaUpperStr`      |               |      | [x]    |         |            |          |\n| `alphaLowerChar`     |               | [x]  |        |         |            |          |\n| `alphaLowerStr`      |               |      | [x]    |         |            |          |\n| `alphaChar`          |               | [x]  |        |         |            |          |\n| `alphaStr`           |               |      | [x]    |         |            |          |\n| `alphaNumChar`       |               | [x]  |        |         |            |          |\n| `alphaNumStr`        |               |      | [x]    |         |            |          |\n| `asciiChar`          |               | [x]  |        |         |            |          |\n| `asciiStr`           |               |      | [x]    |         |            |          |\n| `asciiPrintableChar` |               | [x]  |        |         |            |          |\n| `asciiPrintableStr`  |               |      | [x]    |         |            |          |\n| `posNum`             | [x]           |      |        |         |            |          |\n| `negNum`             | [x]           |      |        |         |            |          |\n| `const`              | [x]           | [x]  | [x]    | [x]     | [x]        | [x]      |\n| `range`              | [x]           | [x]  |        |         | [x]        | [x]      |\n| `oneof`              | [x]           | [x]  | [x]    | [x]     | [x]        | [x]      |\n\n### String definitions\nString definition can be complicated with size restriction.\n\n```\n\u003cdefinition\u003e   ::= \u003cterm\u003e \":\" \u003crestriction\u003e\n\u003crestriction\u003e  ::= \u003cstrict\u003e\n                 | \u003cgreater-then\u003e\n                 | \u003cless-then\u003e       \n\u003cstrict\u003e       := DIGIT+\n\u003cgreater-then\u003e := \"\u003e\" DIGIT+\n\u003cless-then\u003e    := \"\u003c\" DIGIT+\n```\nExamples\n```\nidentifier: 16\nnumStr: \u003c 8\nasciiStr: \u003e 0\n``` \n\n### Const definition\n`const` definition will result in `Gen.const` with given value if converted to specified type.\n\n```\n\u003cdefinition\u003e   ::= \"const\" \":\" \u003cvalue\u003e\n\u003cvalue\u003e        ::= \u003cany\u003e\n```\n\nExamples\n```\nconst: 5\nconst: foo bar baz\nconst: 2018-04-04T00:00Z\n```  \n\n### Range definition\n`range` definition will result in `Gen.choose` with given value if converted to specified type.\n\n```\n\u003cdefinition\u003e   ::= \"range\" \":\" \u003cvalue\u003e \"..\" \u003cvalue\u003e\n\u003cvalue\u003e        ::= \u003cany\u003e\n```\nExamples\n```\nrange: 5 .. 12 // numeric\nrange: 2016-04-04T00:00Z .. 2018-04-04T00:00Z // date\nrange: 5ns .. 8m // duration\n```  \n\n### OneOf definition\n`oneof` definition will result in `Gen.choose` with given value if converted to specified type.\n\n```\n\u003cdefinition\u003e   ::= \"oneof\" \":\" \u003cvalue\u003e (\",\" \u003cvalue\u003e)*\n\u003cvalue\u003e        ::= \u003cany\u003e\n```\nExamples\n```\noneof: 1, 2, 3, 76 // numeric\noneof: 2016-04-04T00:00Z, 2018-04-04T00:00Z // date\noneof: 5ns, 8m, 32d // duration\n```  \n\n## How to use\n\n###### SBT\n```scala\nlibraryDependencies += \"com.github.andyglow\" %% \"scalacheck-gen-configured\" % \"$latestVersion\"\n```\n###### Gradle\n```\ncompile \"com.github.andyglow:scalacheck-gen-configured_${scalaVersion}:$latestVersion\"\n```\n###### Maven\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ecom.github.andyglow\u003c/groupId\u003e\n    \u003cartifactId\u003escalacheck-gen-configured_${scalaVersion}\u003c/artifactId\u003e\n    \u003cversion\u003e$latestVersion\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## TODO\n- [ ] options\n- [ ] containers (`List`, `Set`, `Map`, etc)\n- [ ] handle strings quoted (especially important when used woth `oneof`)\n- [ ] enums\n- [ ] case classes\n- [x] allow pluggable definition formats. now it's strings only, but could be something else (consider typesafe `Config`, json `AST`, ...)\n- [ ] implement typesafe-config enabled `DefnFormat`\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyglow%2Fscalacheck-gen-configured","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fandyglow%2Fscalacheck-gen-configured","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fandyglow%2Fscalacheck-gen-configured/lists"}