{"id":28412704,"url":"https://github.com/vbauer/jconditions","last_synced_at":"2025-06-24T13:31:28.846Z","repository":{"id":142264896,"uuid":"41627313","full_name":"vbauer/jconditions","owner":"vbauer","description":"Extra conditional annotations for JUnit 4","archived":false,"fork":false,"pushed_at":"2018-11-05T08:46:57.000Z","size":131,"stargazers_count":26,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-03T11:55:08.069Z","etag":null,"topics":["conditional-annotations","custom-annotation","java","junit","junit-runner","junit4","testing","unit-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/vbauer.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}},"created_at":"2015-08-30T12:03:10.000Z","updated_at":"2020-12-25T19:38:28.000Z","dependencies_parsed_at":null,"dependency_job_id":"5bad598a-e194-41f0-bc02-2beadb77898e","html_url":"https://github.com/vbauer/jconditions","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/vbauer/jconditions","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbauer%2Fjconditions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbauer%2Fjconditions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbauer%2Fjconditions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbauer%2Fjconditions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/vbauer","download_url":"https://codeload.github.com/vbauer/jconditions/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/vbauer%2Fjconditions/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261685456,"owners_count":23194108,"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":["conditional-annotations","custom-annotation","java","junit","junit-runner","junit4","testing","unit-testing"],"created_at":"2025-06-02T23:44:47.240Z","updated_at":"2025-06-24T13:31:28.827Z","avatar_url":"https://github.com/vbauer.png","language":"Java","readme":"\n# JConditions\n\n[![Android Arsenal](https://img.shields.io/badge/Android%20Arsenal-JConditions-brightgreen.svg?style=flat)](http://android-arsenal.com/details/1/2414)\n[![Build Status](https://travis-ci.org/vbauer/jconditions.svg)](https://travis-ci.org/vbauer/jconditions)\n[![Coverage Status](https://coveralls.io/repos/vbauer/jconditions/badge.svg?branch=master)](https://coveralls.io/r/vbauer/jconditions?branch=master)\n[![Dependency Status](https://www.versioneye.com/user/projects/562e9efb36d0ab001600163a/badge.svg?style=flat)](https://www.versioneye.com/user/projects/562e9efb36d0ab001600163a)\n[![Maven](https://img.shields.io/github/tag/vbauer/jconditions.svg?label=maven)](https://jitpack.io/#vbauer/jconditions)\n\n\u003cimg align=\"right\" style=\"margin-left: 15px\" width=\"200\" height=\"200\" src=\"misc/logo.png\" /\u003e\n\n\u003e There is an exception to every rule.\n\n**JConditions** is an extension for [JUnit](http://junit.org) framework, which allows to mark test methods with specific conditional annotations.\nThis annotations allow to permit or restrict execution of test methods.\nIt helps to keep clean your test methods using declarative programming and prevents a lot of unnecessary code (see [Assume](http://junit.sourceforge.net/javadoc/org/junit/Assume.html) class).\n\n\n## 10 second example\n\nA picture paints a thousand words:\n\n```java\n@RunWith(ConditionTestRunner.class)\npublic class ExampleTest {\n    @Test\n    @RunningOnOS(LINUX)\n    public void testRunningOnOS() throws Exception {\n        // Check some Linux app\n        assertTrue(exec(\"some-linux-program\"));\n    }    \n    @Test\n    @IfJavaVersion(JAVA_8)\n    public void testIfJavaVersion8() {\n        // Check some Java 8 specific code\n        assertTrue(com.foo.Java8Class.isCorrect());\n    }   \n}\n```\n\n\n## Features\n\n**JConditions** has the following conditional annotations:\n\n\u003cul\u003e\n    \u003cli\u003e\u003ca href=\"#appisinstalled\"\u003e@AppIsInstalled\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#existsonfs\"\u003e@ExistsOnFS\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#hasclass\"\u003e@HasClass\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#hasfreespace\"\u003e@HasFreeSpace\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#haspackage\"\u003e@HasPackage\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#ifjavaversion\"\u003e@IfJavaVersion\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#ifscript\"\u003e@IfScript\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#ignoreif\"\u003e@IgnoreIf\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#propertyisdefined\"\u003e@PropertyIsDefined\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#resourceisavailable\"\u003e@ResourceIsAvailable\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#runif\"\u003e@RunIf\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#runningonos\"\u003e@RunningOnOS\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#socketisopened\"\u003e@SocketIsOpened\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#urlisreachable\"\u003e@UrlIsReachable\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\nThis annotations could be used with test methods or/and classes (it will allow to run checks before each test method).\nYou can also write \u003ca href=\"#custom-annotations\"\u003ecustom annotations\u003c/a\u003e or make \u003ca href=\"#composite-annotations\"\u003ecomposite annotations\u003c/a\u003e. \n\n## Setup\n\n**JConditions** uses [JitPack.io](https://jitpack.io) for distribution, so\nyou need to configure JitPack's Maven repository to fetch artifacts (dependencies).\n\n### Maven\n\n```xml\n\u003crepository\u003e\n    \u003cid\u003ejitpack.io\u003c/id\u003e\n    \u003curl\u003ehttps://jitpack.io\u003c/url\u003e\n\u003c/repository\u003e\n\n\u003cdependencies\u003e\n    \u003cdependency\u003e\n        \u003cgroupId\u003ecom.github.vbauer\u003c/groupId\u003e\n        \u003cartifactId\u003ejconditions\u003c/artifactId\u003e\n        \u003cversion\u003e1.2.3\u003c/version\u003e\n    \u003c/dependency\u003e\n\u003c/dependencies\u003e\n```\n\n### Gradle\n\n```groovy\nrepositories {\n    mavenCentral()\n    maven {\n        url 'https://jitpack.io'\n    }\n}\n\ndependencies {\n    testCompile 'com.github.vbauer:jconditions:1.2.3'\n}\n```\n\n\n## Annotations\n\nSome things that you need to know before exploring an examples:\n\n* Each described annotation has a simple example how to use it. Examples are very simple, they are existed only to show the main idea of usage.\n* Most of them could use injections to insert environment variables. This injections/substitutions could be useful to parametrize tests or to organize profiles.\n**EX:** \"${java.io.tmpdir}/test.html\"\n\n### @AppIsInstalled\n**@AppIsInstalled** checks that specified application(s) is installed.\nIt could be useful when developed application has an optional integrations with some external tools/apps and \nit will be good to check this integrations in tests.\n\n```java\n@Test\n@AppIsInstalled({ \"ls\", \"uname\" })\npublic void testAppIsInstalled() throws Exception {\n    exec(\"ls\");\n    exec(\"uname\");\n}\n```\n\n### @ExistsOnFS\n**@ExistsOnFS** checks that specified file or directory is existed on file system.\nIt is also possible to configure multiple values.\n\nAvailable parameters:\n\n* **value** - file(s) or directory(ies).\n* **type** - type(s) of FS element (FILE / DIRECTORY / SYMLINK).\n\n```java\n@Test\n@ExistsOnFS(\"pom.xml\")\npublic void testFileExists() throws Exception {\n    Assert.assertTrue(FSUtils.fileExists(\"pom.xml\"));\n}\n```\n\n### @HasClass\n**@HasClass** checks that specified class(es) is available in classpath.\nIt could be useful to check integration with optional features.\n\n```java\n@Test\n@HasClass(\"org.junit.Assert\")\npublic void testHasClass() throws Exception {\n    Assert.assertNotNull(Class.forName(\"org.junit.Assert\"));\n}\n```\n\n### @HasFreeSpace\n**@HasFreeSpace** checks that FS element(s) / disk(s) has free space.\nIt could be useful to check if it is possible to:\n\n* download some big some file from remote server\n* generate and store on FS some data\n\nAvailable parameters:\n\n* **value** - disk or disks that should be checked (ex: \"C:\\\\\").\n* **min** - minimum amount of available free space on disk in bytes.\n* **max** - maximum amount of available free space on disk in bytes.\n\n```java\n@Test\n@HasFreeSpace(value = { \"/\", \"C:\\\\\" }, min = 1024)\npublic void testHasFreeSpace() {\n    // Download some file\n}\n```\n\n### @HasPackage\n**@HasPackage** checks that specified package(s) is available in classpath.\nIt could be useful to check integration with optional features.\n\n```java\n@Test\n@HasPackage(\"org.junit\")\npublic void testHasPackage() throws Exception {\n    Assert.assertNotNull(Package.getPackage(\"org.junit\"));\n}\n```\n\n### @IfJavaVersion\n**@IfJavaVersion** checks that test is run on the specific version(s) of JVM.\n\n**EX:** Some features could use external libraries and work only for the specific version of JVM.\nIt is possible to check it, if you use full names for classes (class loader will load them in runtime).\n\n```java\n@Test\n@IfJavaVersion(IfJavaVersion.JAVA_8)\npublic void testIfJavaVersion8() {\n    Assert.assertTrue(IfJavaVersionChecker.javaVersion().contains(\"8\"));\n    // Javaslang project works only on Java 8\n    Assert.assertNotNull(javaslang.Tuple0.instance());\n}\n```\n\n### @IfScript\n\n**@IfScript** allows to write custom conditional rules using [JSR 223: Scripting for the JavaTM Platform](https://www.jcp.org/en/jsr/detail?id=223).\nJavaScript engine is available by default (it is part of JVM).\nAll other JSR233-compatible languages will be included automatically if they are available in classpath.\n\nAvailable parameters:\n\n* **values** - script or scripts that should be executed. Return value will be converted to boolean type (even `String` and `Number`s).\n* **engine** - type of script engine (default value is `\"js\"`).\n* **context** - context provider which provides an extra data in script as `\"context\"` variable.\n\n\nParameters which are available in script context:\n\n* **test** - current instance of running test class.\n* **env** - environment variables (`System.getenv()`).\n* **props** - system properties (`System.getProperties()`).\n* **console** - console object (`System.console()`).\n* **context** - extra data which could be created using `context` provider.\n \n```java\n@Test\n@IfScript(\"test.isSatisfiedInnerCheck\")\npublic void testIfScriptNegative() {\n    Assert.fail();\n}\n```\n\n### @IgnoreIf\n**@IgnoreIf** allows to skip some test method using specific `ConditionChecker` class.\nIt will skip test, if checker return true and execute method otherwise.\n`ConditionChecker` could be separate class, or nested static class, or even inner class.\nIt also works fine with private classes.\n\n```java\n@Test\n@IgnoreIf(Always.class)\npublic void testIgnoreIfAlways() {\n    Assert.fail();\n}\n```\n\n### @PropertyIsDefined\n\n**@PropertyIsDefined** checks if environment or system property is defined.\n It could be useful to simulate test profiles or to check some cases which are dependent on them (and could be optionals).\n \n Available parameters:\n \n * **keys** - keys of environment or system variables\n * **values** - values that should correspond to keys (optional parameter).\n\n```java\n@Test\n@PropertyIsDefined(keys = \"os.name\")\npublic void testEnvVarIsDefined() {\n    Assert.assertNotNull(PropUtils.getSystemProperty(\"os.name\"));\n}\n```\n\n### @ResourceIsAvailable\n\n**@ResourceIsAvailable** allows to minimize code which is necessary to download some document/file via HTTP/HTTPS.\nIt is also possible to cache downloaded resource between test executions, otherwise it will be remove after test.\n\nAvailable parameters:\n\n* **source** - HTTP/HTTPS file or document.\n* **target** - path to file where content should be saved.\n* **cache** - flag to configure cache option.\n* **timeout** - maximum time for connection to the `source` (default value is 10sec).\n\n```java\n@Test\n@ResourceIsAvailable(\n    source = \"http://apple.com\",\n    target = \"${java.io.tmpdir}/apple-homepage.html\",\n    cache = false\n)\npublic void testResourceIsAvailable() {\n    final String path = PropUtils.injectProperties(\"${java.io.tmpdir}/apple-homepage.html\");\n    Assert.assertTrue(FSUtils.fileExists(path));\n}\n```\n\n### @RunIf\n\n**@RunIf** is an opposite annotation to **@IgnoreIf**. It will run test method if `ConditionChecker` returns `true`.\n\n```java\n@Test\n@RunIf(SomeInnerClassCheck.class)\npublic void testInnerClass() {\n    Assert.fail();\n}\n```\n\n### @RunningOnOS\n**@RunningOnOS** checks the current operation system and runs test method only when it is specified and `value` parameter.\nIt is also possible to configure multiple variants (to run test method, even one of them should be fine).\n\n```java\n@Test\n@RunningOnOS({\n    RunningOnOS.LINUX,\n    RunningOnOS.MAC,\n})\npublic void testRunningOnOS() throws Exception {\n    Assert.assertTrue(exec(\"ls\"));\n}\n```\n\n### @SocketIsOpened\n**@SocketIsOpened** checks that specified socket is opened.\n\nAvailable parameters:\n\n* **host** - host address (default value is \"0.0.0.0\").\n* **port** - socket's port number.\n* **timeout** - maximum time for connection to the socket (default value is 10sec).\n\n```java\n@Test\n@SocketIsOpened(host = \"apple.com\", port = 80)\npublic void testSocketIsOpened() throws Exception {\n    checkSite(\"http://apple.com\");\n}\n```\n\n### @UrlIsReachable\n\n**@UrlIsReachable** checks that specified URL address is reachable (available via `URLConnection`).\nIt also possible to configure multiple URLs.\n\nAvailable parameters:\n\n* **value** - URL address(s) that should be checked.\n* **timeout** - maximum timeout for URL connection (default value is 10sec).\n\n```java\n@Test\n@UrlIsReachable(\"http://apple.com\")\npublic void testUrlIsReachable() throws Exception {\n    checkSite(\"http://apple.com\");\n}\n```\n\n\n## Custom annotations\nIt is possible use `@IfRun` or `@IgnoreIf` to run custom `ConditionalChecker`,\nbut it is also possible to write your own annotation (like `@HasPackage` or `@IfScript`).\n\nAll JConditions out-of-box annotations was created using unified extension mechanism.\nThis mechanism is centered around 3 main things:\n\n* Custom annotation which can has additional parameters that could be used as input data.\n* Conditional checker which make decision to permit or restrict running of test method.\n* `@Condition` annotation which allows to glue custom annotation and conditional checker.\n\nLet's write an annotation which emulates standard JUnit's `@org.junit.Ignore`:\n\n```java\n@Condition(IgnoreItChecker.class)\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD })\npublic @interface IgnoreIt {\n}\n\npublic class IgnoreItChecker implements ConditionChecker\u003cIgnoreIt\u003e {\n    @Override\n    public boolean isSatisfied(final CheckerContext\u003cIgnoreIt\u003e context) {\n        return false;\n    }\n\n}\n```\n\nThat's all! Now, you can mark test classes or test methods with `@IgnoreIt` to skip test(s).\n\n\n## Composite annotations\n\nSometimes it could be useful to have possibility to resolve the following cases (to prevent unnecessary code):\n\n* Specify all needed parameter for some existed annotation and do not copy-paste them.\n* Glue some conditional annotations into one annotation.\n\nIt is possible, because JConditions extension mechanism resolves all hierarchy of classes and annotations.\n\nLet's make an annotation which allows to detect if our MySQL database works fine:\n\n```java\n@SocketIsOpened(host = \"localhost\", port = 3306)\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })\npublic @interface MySQLWorks {\n}\n```\n\nLet's make an annotation which allows to run tests only on Linux machines with Java 8:\n\n```java\n@RunningOnOS(LINUX)\n@IfJavaVersion(JAVA_8)\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })\npublic @interface OnLinuxWithJava8 {\n}\n```\n\n\n## Building from source\n\nJConditions uses [Maven](https://maven.apache.org) for its build. To build project, run:\n\n```bash\nmvn clean install -P strict\n```\n\nfrom the root of the project directory.\nProfile `strict` is necessary to check code style and to run static code analysis.\n\n\n## Might also like\n\n* [jackdaw](https://github.com/vbauer/jackdaw) - Java Annotation Processor which allows to simplify development.\n* [caesar](https://github.com/vbauer/caesar) - Library that allows to create async beans from sync beans.\n* [houdini](https://github.com/vbauer/houdini) - Type conversion system for Spring framework.\n* [herald](https://github.com/vbauer/herald) - Logging annotation for Spring framework.\n* [commons-vfs2-cifs](https://github.com/vbauer/commons-vfs2-cifs) - SMB/CIFS provider for Commons VFS.\n* [avconv4java](https://github.com/vbauer/avconv4java) - Java interface to avconv tool.\n\n\n## License\n\nCopyright 2015 Vladislav Bauer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n    http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nSee [LICENSE](LICENSE) file for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbauer%2Fjconditions","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvbauer%2Fjconditions","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvbauer%2Fjconditions/lists"}