{"id":19765721,"url":"https://github.com/openhft/chronicle-test-framework","last_synced_at":"2026-01-29T01:13:14.543Z","repository":{"id":38202839,"uuid":"421820611","full_name":"OpenHFT/Chronicle-Test-Framework","owner":"OpenHFT","description":null,"archived":false,"fork":false,"pushed_at":"2024-04-12T08:36:45.000Z","size":308,"stargazers_count":23,"open_issues_count":2,"forks_count":6,"subscribers_count":12,"default_branch":"ea","last_synced_at":"2024-04-12T15:34:00.360Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/OpenHFT.png","metadata":{"files":{"readme":"README.adoc","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}},"created_at":"2021-10-27T13:02:33.000Z","updated_at":"2024-04-15T13:04:19.804Z","dependencies_parsed_at":"2023-02-13T04:30:44.166Z","dependency_job_id":"f73bbef5-c433-4ec2-9ec9-886ca2cfa7eb","html_url":"https://github.com/OpenHFT/Chronicle-Test-Framework","commit_stats":null,"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Test-Framework","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Test-Framework/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Test-Framework/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/OpenHFT%2FChronicle-Test-Framework/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/OpenHFT","download_url":"https://codeload.github.com/OpenHFT/Chronicle-Test-Framework/tar.gz/refs/heads/ea","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224214832,"owners_count":17274690,"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":[],"created_at":"2024-11-12T04:19:14.279Z","updated_at":"2026-01-29T01:13:14.538Z","avatar_url":"https://github.com/OpenHFT.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"= Chronicle Test Framework\n\n:css-signature: demo\n:toc: macro\n:toclevels: 2\n:icons: font\n\nimage:https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-test-framework/badge.svg[Maven Central,link=https://maven-badges.herokuapp.com/maven-central/net.openhft/chronicle-test-framework]\nimage:https://javadoc.io/badge2/net.openhft/chronicle-test-framework/javadoc.svg[Javadoc,link=\"https://www.javadoc.io/doc/net.openhft/chronicle-test-framework/latest/index.html\"]\n//image:https://javadoc-badge.appspot.com/net.openhft/chronicle-test-framework.svg?label=javadoc[JavaDoc, link=https://www.javadoc.io/doc/net.openhft/chronicle-test-framework]\nimage:https://img.shields.io/github/license/OpenHFT/Chronicle-Test-Framework[Licence]\nimage:https://img.shields.io/badge/release%20notes-subscribe-brightgreen[Release Notes,link=\"https://chronicle.software/release-notes/\"]\nimage:https://sonarcloud.io/api/project_badges/measure?project=OpenHFT_ChronicleTestFramework\u0026metric=alert_status[Quality Gate,link=\"https://sonarcloud.io/dashboard?id=OpenHFT_Chronicle-Test-Framework\"]\n\ntoc::[]\n\n== About\n\nChronicle Test Framework provides test-data generators and API metrics tools for JUnit 4 and JUnit 5. Use the combinators to create permutations, combinations and products, or analyse your packages with the metrics builder.\n\n== Permutations\n\nPermutations work like this:\n\n[source,java]\n----\n@Test\nvoid print() {\n    Permutation.of(\"A\", \"B\", \"C\")\n            .forEach(System.out::println);\n}\n----\n\nThis will produce the following output:\n\n[source,text]\n----\n[A, B, C]\n[A, C, B]\n[B, A, C]\n[B, C, A]\n[C, A, B]\n[C, B, A]\n----\n\nTesting using permutations:\n\n[source,java]\n----\n@TestFactory\n// Exhaustively verifies that any order of setter invocation yields the same result\nStream\u003cDynamicTest\u003e demo() {\n    // Operations\n    final Consumer\u003cMyBean\u003e setA = myBean -\u003e myBean.setA(1);\n    final Consumer\u003cMyBean\u003e setB = myBean -\u003e myBean.setB(2);\n    final Consumer\u003cMyBean\u003e setC = myBean -\u003e myBean.setC(3);\n    final MyBean expected = new MyBean(1, 2, 3);\n    // DynamicTests\n    return DynamicTest.stream(Permutation.of(setA, setB, setC),\n            Objects::toString,\n            operations -\u003e {\n                final MyBean actual = new MyBean();\n                operations.forEach(oper -\u003e oper.accept(actual));\n                assertEquals(expected, actual);\n            });\n}\n----\n\n== API Metrics Builder\n\nThe API metrics feature analyses the public and internal surface of your packages.\nCreate the builder via `ApiMetrics.builder()` then supply the packages to scan, the metrics to apply and the accumulators that gather the results.\n\n[source,java]\n----\nApiMetrics metrics = ApiMetrics.builder()\n        .addStandardMetrics()\n        .addStandardAccumulators()\n        .addPackage(\"com.example\")\n        .build();\n----\n\nThe builder applies no defaults.\nIf you omit metrics or accumulators the result will be empty.\nDefault metrics and accumulators are only added when you call the relevant `addStandard` methods.\nPackages with `.internal.` in the name, or those ending in `.internal`, are collected in a separate internal group.\n\n== Combinations\n\nCombinations work like this:\n\n[source,java]\n----\n@Test\nvoid print() {\n    Combination.of(\"A\", \"B\", \"C\")\n            .forEach(System.out::println);\n}\n----\n\nThis will produce the following output:\n\n[source,text]\n----\n[]\n[A]\n[B]\n[C]\n[A, B]\n[A, C]\n[B, C]\n[A, B, C]\n----\n\nTesting using combinations:\n\n[source,java]\n----\n@TestFactory // Try all combinations of cosmic ray interference for the Robot state machine\nStream\u003cDynamicTest\u003e demo() {\n        return DynamicTest.stream(Combination.\u003cConsumer\u003cFaultTolerantBitSet\u003e\u003eof(\n                        FaultTolerantBitSet::cosmicRayBit3,\n                        FaultTolerantBitSet::cosmicRayBit23,\n                        FaultTolerantBitSet::cosmicRayBit13),\n                Objects::toString,\n                operations -\u003e {\n                    final FaultTolerantBitSet bitSet = new FaultTolerantBitSet();\n                    operations.forEach(oper -\u003e oper.accept(bitSet));\n                    assertTrue(bitSet.isValid());\n                });\n    }\n----\n\n== Combinations and Permutations\n\nCombinations and Permutations can be combined to create powerful exhaustive test vectors:\n\n[source,java]\n----\n    @Test\n    void demo() {\n        Combination.of(\"A\", \"B\", \"C\")\n                .flatMap(Permutation::of)\n                .forEach(System.out::println);\n    }\n----\n\nThis will produce the following output:\n\n[source,text]\n----\n[]\n[A]\n[B]\n[C]\n[A, B]\n[B, A]\n[A, C]\n[C, A]\n[B, C]\n[C, B]\n[A, B, C]\n[A, C, B]\n[B, A, C]\n[B, C, A]\n[C, A, B]\n[C, B, A]\n----\n\n== Products\n\nProducts are equivalent to nested loops but are easier to convert to a `Stream` of `DynamicTest` objects:\n\n[source,java]\n----\n    @Test\n    void print() {\n        Product.of(Arrays.asList(\"A\", \"B\", \"C\"), Arrays.asList(1, 2, 3))\n                .forEach(System.out::println);\n    }\n----\n\nThis will produce the following output:\n\n[source,text]\n----\nProduct2Impl{first=A, second=1}\nProduct2Impl{first=A, second=2}\nProduct2Impl{first=A, second=3}\nProduct2Impl{first=B, second=1}\nProduct2Impl{first=B, second=2}\nProduct2Impl{first=B, second=3}\nProduct2Impl{first=C, second=1}\nProduct2Impl{first=C, second=2}\nProduct2Impl{first=C, second=3}\n----\n\nProducts can use built-in tuples like `Product2Impl` or we can provide custom constructors to use our own.\nTesting using products:\n\n[source,java]\n----\n@TestFactory\n// Exhaustively tests if various empty collections invariants holds\nStream\u003cDynamicTest\u003e demo() {\n    // Operations\n    final List\u003cCollection\u003cInteger\u003e\u003e collections = Arrays.asList(new LinkedList\u003c\u003e(), new ArrayList\u003c\u003e(), new HashSet\u003c\u003e());\n    // Operations\n    final Consumer\u003cCollection\u003cInteger\u003e\u003e empty =\n            c -\u003e assertTrue(c.isEmpty(), c.getClass() + \".empty() was false\");\n    final Consumer\u003cCollection\u003cInteger\u003e\u003e size =\n            c -\u003e assertEquals(0, c.size(), c.getClass() + \".size() != 0\");\n    final Consumer\u003cCollection\u003cInteger\u003e\u003e streamCount =\n            c -\u003e assertEquals(0, c.stream().count(), c.getClass() + \".stream().count() != 0\");\n    final List\u003cConsumer\u003cCollection\u003cInteger\u003e\u003e\u003e operations = Arrays.asList(empty, size, streamCount);\n\n            // DynamicTests\n    return DynamicTest.stream(Product.of(collections, operations),\n            Objects::toString,\n            tuple -\u003e {\n                tuple.second().accept(tuple.first());\n            });\n}\n----\n\n== API Metrics Accumulators\n\nThe framework includes a small set of predefined accumulator suppliers used by the API metrics analysis.\nThey help to group metric counts in common ways.\n\n* `perMethod()` groups by the full method signature so that overloaded methods are reported separately.\n* `perClassAndMetric()` groups first by class and then by metric, giving a table of metric totals for each class.\n* `PER_METRIC` provides totals for each metric across all classes.\n* `PER_CLASS` totals all metrics for each class without distinction.\n* `PER_PACKAGE` reports a single total for each package.\n* `PER_METHOD_REFERENCE` groups by method name only, ignoring parameter types, so all overloads are counted as one.\n\nThe convenience factories in `Accumulator` expose the first two suppliers for general use.\nThe others are mainly for internal analyses but may be reused when custom behaviour is needed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenhft%2Fchronicle-test-framework","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fopenhft%2Fchronicle-test-framework","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fopenhft%2Fchronicle-test-framework/lists"}