{"id":20996928,"url":"https://github.com/menny/junittestsgrouping","last_synced_at":"2025-03-13T13:16:04.337Z","repository":{"id":138997287,"uuid":"85955157","full_name":"menny/JUnitTestsGrouping","owner":"menny","description":"A JUnit Filter that will only execute tests in a specific shard/group/bucket.","archived":false,"fork":false,"pushed_at":"2018-10-01T14:08:02.000Z","size":82,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-20T09:11:40.638Z","etag":null,"topics":["filter","java","junit","junit-filter","loadbalancing","sharding","testing"],"latest_commit_sha":null,"homepage":"","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/menny.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":"2017-03-23T13:50:15.000Z","updated_at":"2018-06-19T18:33:35.000Z","dependencies_parsed_at":null,"dependency_job_id":"1d63de1f-c347-42d8-a70e-a649118c184a","html_url":"https://github.com/menny/JUnitTestsGrouping","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menny%2FJUnitTestsGrouping","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menny%2FJUnitTestsGrouping/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menny%2FJUnitTestsGrouping/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/menny%2FJUnitTestsGrouping/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/menny","download_url":"https://codeload.github.com/menny/JUnitTestsGrouping/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243410459,"owners_count":20286403,"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":["filter","java","junit","junit-filter","loadbalancing","sharding","testing"],"created_at":"2024-11-19T07:38:00.590Z","updated_at":"2025-03-13T13:16:04.263Z","avatar_url":"https://github.com/menny.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# JUnitTestsGrouping\nA JUnit Filter for sharding your JUnit tests.\n\n`master` latest build: [![CircleCI](https://circleci.com/gh/menny/JUnitTestsGrouping/tree/master.svg?style=svg)](https://circleci.com/gh/menny/JUnitTestsGrouping/tree/master)\u003cbr/\u003e\n`master` coverage: [![codecov](https://codecov.io/gh/menny/JUnitTestsGrouping/branch/master/graph/badge.svg)](https://codecov.io/gh/menny/JUnitTestsGrouping)\n\n## Usage\nUsing JUnit's `Suite` or `Filter` mechanism, JUnitTestsGrouping will skip tests that are not in the execution group/shard.\nBasically, it calculated the group index base on the test-class name and if this index equals the execution index\nthe test will execute, otherwise it will be filtered out.\n\n### Setup - Gradle\nAdd JUnitTestsGrouping dependency to your `build.gradle`:\n```\nrepositories {\n    maven { url \"https://jitpack.io\" }\n}\n\ndependencies {\n    testImplementation 'com.github.menny:JUnitTestsGrouping:0.3.0'\n}\n```\n\n### Setup - tests\nThere are two mechanisms in this library: `Filter` or `Suite`\n\n### Setup - tests Filter\nAdd the filter to your JUnit test-runner. In this example, I created a custom `TestRunner`:\n```\npublic class MyTestRunner extends RobolectricTestRunner {\n    public MyTestRunner(Class\u003c?\u003e testClass) throws InitializationError {\n        super(testClass);\n        TestsGroupingFilter.addTestsGroupingFilterWithSystemPropertiesData(this, true);\n    }\n}\n```\n\n### Setup - tests Suite\nCreate an empty class in your tests folder (at the root of the package), and annotate it with `ShardingSuite` and the hashing strategy: \n```\n@RunWith(ShardingSuite.class)\n@ShardingSuite.ShardUsing(TestClassHashingStrategy.class)\npublic class MyTestsSuite {\n}\n```\nOur `ShardingSuite` will scan your `ClassLoader` for all classes that have tests in them, and shard them using the `HashingStrategy` class\nprovided in `@ShardingSuite.ShardUsing`.\nFor Gradle, you will also need to tell Gradle that you want to run this Suite. From command line:\n```\n./gradlew -Dtest.single=MyTestsSuite clean test\n```\nOr, the preferred way, create a `Test` task:\n```\ntask testWithSharding(type: Test) {\n    include '**/MyTestsSuite.class'\n}\n```\n\n\u003cbr/\u003e\n\nFor both mechanisms (Filter or Suite) you will need to set the number of groups to split the tests between, and set the current test group index (also, in your `build.gradle`):\n```\nsystemProperties['TestsGroupingFilter_TEST_GROUP_TO_EXECUTE_SYSTEM_PROPERTY_KEY'] =  System.getenv().getOrDefault('TEST_GROUP_INDEX', 0);\nsystemProperties['TestsGroupingFilter_TEST_GROUPS_COUNT_SYSTEM_PROPERTY_KEY'] = System.getenv().getOrDefault('TEST_GROUPS_COUNT', 1);\n```\n\nWhere the environment variable`TEST_GROUP_INDEX` is the current test-group and `TEST_GROUPS_COUNT` is the total number of test groups.\n\n## Example Scenario 1\nSo, an example could be:\n\n * a Continuous Integration setup where you have 3 machines for running your tests.\n * in each of those machines you will set up\n   * an environment variable `TEST_GROUPS_COUNT=3`,\n   * and `TEST_GROUP_INDEX` which holds the index of the machine (`TEST_GROUP_INDEX=0` for the first, `TEST_GROUP_INDEX=1`\nfor the second and `TEST_GROUP_INDEX=2` for the third).\n\n## Extending for other grouping types\nThe grouping is done by the given `HashingStrategy`, which calculates a hash for the test's `Description` instance, and groups the tests according to that.\n\nBy default, `JUnitTestsGrouping` uses `TestClassHashingStrategy` to group tests: it hashes the test-class name. This ensures that tests that are defined in the same class will run in the same group.\u003cbr\u003e\nYou can change that behavior by providing a different implementation of `HashingStrategy` when constructing `TestsGroupingFilter`.\u003cbr\u003e\nFor example, you may want to group tests by an `Annotation`:\n```\npublic class AnnotationHashingStrategy extends SimpleHashingStrategyBase {\n\n    @Override\n    public int calculateHashFromDescription(Description description) {\n        final Class testClass = description.getTestClass();\n        if (testClass.getAnnotation(Marker1.class) != null) return 0;\n        if (testClass.getAnnotation(Marker2.class) != null) return 1;\n        if (testClass.getAnnotation(Marker3.class) != null) return 2;\n        \n        return 3;\n    }\n}\n```\n\n\nSimilar strategy is implemented in `AnnotationHashingStrategy`.\n\n## Example Scenario 2 - this library\nIn this library, we use the `Suite` mechanism in a non-standard way: we use the `HashingStrategy` to filter out test-classes that are\nused as input in the tests - when our [strategy](https://github.com/menny/JUnitTestsGrouping/blob/master/src/test/java/net/evendanan/testgrouping/inputs/TestableHashingStrategy.java)\nsees classes in the `inputs` package, it returns `-1`, which will ensure these classes are not executed.\n\n\n## License\n```\n    Copyright 2018 Menny Even-Danan\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmenny%2Fjunittestsgrouping","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmenny%2Fjunittestsgrouping","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmenny%2Fjunittestsgrouping/lists"}