{"id":19666169,"url":"https://github.com/jkschneider/java-power-assert","last_synced_at":"2025-04-28T22:31:37.934Z","repository":{"id":57735681,"uuid":"59227937","full_name":"jkschneider/java-power-assert","owner":"jkschneider","description":null,"archived":false,"fork":false,"pushed_at":"2021-07-14T23:23:19.000Z","size":2277,"stargazers_count":94,"open_issues_count":7,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-05T11:34:18.461Z","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/jkschneider.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}},"created_at":"2016-05-19T17:30:27.000Z","updated_at":"2024-12-08T03:16:05.000Z","dependencies_parsed_at":"2022-08-24T03:30:31.265Z","dependency_job_id":null,"html_url":"https://github.com/jkschneider/java-power-assert","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jkschneider%2Fjava-power-assert","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jkschneider%2Fjava-power-assert/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jkschneider%2Fjava-power-assert/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jkschneider%2Fjava-power-assert/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jkschneider","download_url":"https://codeload.github.com/jkschneider/java-power-assert/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251397629,"owners_count":21583042,"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-11T16:26:38.623Z","updated_at":"2025-04-28T22:31:35.062Z","avatar_url":"https://github.com/jkschneider.png","language":"Java","funding_links":[],"categories":["测试"],"sub_categories":[],"readme":"# Power Assertions for Java\n\n[![Build Status](https://travis-ci.org/jkschneider/java-power-assert.svg?branch=master)](https://travis-ci.org/jkschneider/java-power-assert)\n[![Apache 2.0](https://img.shields.io/github/license/jkschneider/java-power-assert.svg)](http://www.apache.org/licenses/LICENSE-2.0)\n\nPower assertions (a.k.a. diagrammed assertions) augment your assertion failures with information about values produced during the evaluation of a condition, and presents them in an easily digestible form.\nPower assertions are a popular feature of [Spock](https://github.com/spockframework/spock) (and later the whole [Groovy](https://github.com/apache/groovy) language independently of Spock),\n[ScalaTest](http://www.scalatest.org/), and [Expecty](https://github.com/pniederw/expecty).\n\n#### Java `assert` keyword\n\nThe plain java assert keyword is replaced with a diagrammed assertion. For example, the assertion\n\n```java\nassert Character.isWhitespace(\"abc\".charAt(0));\n```\n\nproduces this diagram:\n\n    Character.isWhitespace(\"abc\".charAt(0))\n              |                  |\n              false              a\n\n#### JUnit\n\nJUnit `assertXXX` invocations are also diagrammed. The assertion\n\n```java\nint[] a = new int[] { 1, 2, 3 };\nint[] b = new int[] { 1, 2, 4 };\nassertArrayEquals(a, b);\n```\n\nproduces this diagram:\n\n    assertArrayEquals(a, b)\n                      |  |\n                      |  [1, 2, 4]\n                      [1, 2, 3]\n\nRegular JUnit assert output is suppressed in favor of the more descriptive diagram.\n\n#### Hamcrest\n\nBut wait, there's more! Hamcrest `assertThat` invocations are also diagrammed. The assertion\n\n```java\nInteger a = 2;\nassertThat(1, equalTo(a));\n```\n\nproduces this diagram:\n\n    assertThat(1, equalTo(a))\n                   |      |\n                   \u003c2\u003e    2\n\nRegular Hamcrest assert output is suppressed in favor of the more descriptive diagram, however, the `Matcher` itself\nis diagrammed, so sophisticated descriptions will still be in the output.\n\n\n#### Non-Goals\n\njava-power-assert does not change the semantics of equality in Java. Every power-asserted statement will yield the same result as if it were left unchanged. In other words, if you turn off annotation processing during your build process or in your IDE, you can expect your tests to pass or fail just as they would if java-power-assert's annotation processing was doing its magic, you just would not see diagrammed output.\n\n## Limitations\n\nCurrently, java-power-assert only works on code compiled with javac. This means it works in IntelliJ IDEA, gradle, etc.\n\nNotably, it does *not* work in Eclipse which uses the Eclipse Compiler for Java (ECJ). There is\n a known solution for ECJ that involves running Eclipse with a Java agent that intercepts the ECJ generated AST prior to bytecode generation (and indeed this is what\n [Lombok](https://github.com/rzwitserloot/lombok) does). It is currently unknown whether it is possible to access the ECJ AST from a regular annotation processor.\n \nAlso, in the same way we diagram JUnit and Hamcrest assertions, we could trivially expand to assertj `assertThat` style chains. Contributions welcome if you beat me to it!\n\n## A special note about Java 8\n\nJava 8 saw a significant regression in type inference performance ([details here](https://bugs.openjdk.java.net/browse/JDK-8067767)).\nIn short, the time it takes to infer types for nested generic method calls without explicit type arguments grows exponentially in JDK 8.\nThis was *not* a problem in JDK 7 and has already been fixed in JDK 9, but Oracle does not intend to fix this in Java 8.\nBecause the method we use to record values is generic itself, we have no choice but to arbitrarily limit the depth at which we can record values on Java 8. So a statement like:\n\n    @org.junit.Test public void test() {\n        Data d = new Data();\n        assert d.ident().ident().ident().ident() == null\n    }\n\nYields a diagram like this:\n\n    d.ident().ident().ident().ident() == null,\n                     |       |        |\n                     Data[]  Data[]   false\n\n## Getting started\n\nAll you need to do is include `java-power-assert` as a dependency and turn on annotation processing in your IDE.\nCurrently it released only in [BinTray](https://bintray.com/jkschneider/maven/java-power-assert) so you need to add this repository first.\n\n#### Gradle\nAdd the repository:\n```groovy\nrepositories {\n  maven {\n    url  \"https://dl.bintray.com/jkschneider/maven\" \n  }\n}\n```\n\nAnd add the dependency:\n```groovy\ntestCompile 'io.jschneider:java-power-assert:latest.release'\n```\n\n#### Maven\nAdd the repository into your `pom.xml`:\n```xml\n\u003crepositories\u003e\n  \u003crepository\u003e\n    \u003cid\u003ebintray-jkschneider-maven\u003c/id\u003e\n    \u003cname\u003ebintray-jkschneider-maven\u003c/name\u003e\n    \u003curl\u003ehttps://dl.bintray.com/jkschneider/maven\u003c/url\u003e\n  \u003c/repository\u003e\n\u003c/repositories\u003e\n```\n\nAnd add the dependency:\n```xml\n\u003cdependency\u003e\n  \u003cgroupId\u003eio.jschneider\u003c/groupId\u003e\n  \u003cartifactId\u003ejava-power-assert\u003c/artifactId\u003e\n  \u003cversion\u003e0.9.1\u003c/version\u003e\n  \u003cscope\u003etest\u003c/scope\u003e\n\u003c/dependency\u003e\n```\n\n## How does it work?\n\nAn annotation processor (`PowerAssertProcessor`) looks for assert statements and replaces the AST representing the assert statement with a few statements that record the values of fields, method invocations, etc produced during the evaluation of the expression. When the original assert condition would have produced a false value, java-power-assert throws an `AssertionError` with a diagram of expression values as the exception message.\n\n## Examples\n\n```java\npublic class PowerAssertExampleTest {\n\t@Test\n\tpublic void methodInvocation() {\n\t\tassert Character.isWhitespace(\"abc\".charAt(0));\n\n\t\t/*\n\t\tCharacter.isWhitespace(\"abc\".charAt(0))\n\t\t\t\t  |                  |\n\t\t\t\t  false              a\n\t\t */\n\t}\n\n\t@Test\n\tpublic void chainedMethodInvocation() {\n\t\tassert \"abc\".substring(0).contains(\"d\");\n\n\t\t/*\n\t\t\"abc\".substring(0).contains(\"d\")\n\t\t\t  |            |\n\t\t\t  abc          false\n\t\t */\n\t}\n\n\t@Test\n\tpublic void propertyRead() {\n\t\tData d = new Data(\"abc\");\n\t\tassert d.field.equals(\"def\");\n\n\t\t/*\n\t\td.field.equals(\"def\")\n\t\t| |     |\n\t\t| abc   false\n\t\tData[field=abc]\n\t\t */\n\t}\n\n\t@Test\n\tpublic void identifiers() {\n\t\tString a = \"abc\";\n\t\tassert a == \"def\";\n\n\t\t/*\n\t\ta == \"def\"\n\t\t|  |\n\t\t|  false\n\t\tabc\n\t\t */\n\t}\n\n\t@Test\n\tpublic void binaryExpression() {\n\t\t// notice how whitespace is preserved in the output\n\t\tassert 1+ 1 == 3;\n\n\t\t/*\n\t\t1+ 1 == 3\n\t\t |    |\n\t\t 2    false\n\t\t */\n\t}\n\n\t@Test\n\tpublic void unaryExpression() {\n\t\tassert !true;\n\n\t\t/*\n\t\t!true\n\t\t|\n\t\tfalse\n\t\t */\n\t}\n\n\t@Test\n\tpublic void nullValues() {\n\t\tString a = null;\n\t\tassert \"null\".equals(a);\n\n\t\t/*\n\t\t\"null\".equals(a)\n\t\t\t   |      |\n\t\t\t   false  null\n\t\t */\n\t}\n\n\t@Test\n\tpublic void arrayAccess() {\n\t\tint n[] = new int[] { 0, 1, 2 };\n\t\tassert n[0] == 1;\n\n\t\t/*\n\t\tn[0] == 1\n\t\t||    |\n\t\t|0    false\n\t\t[0, 1, 2]\n\t\t */\n\t}\n\n\t@Test\n\tpublic void newArray() {\n\t\tint i = 1;\n\t\t// extraordinarily contrived, I know...\n\t\tassert new int[] { i }[0] == 2;\n\n\t\t/*\n\t\tnew int[] { i }[0] == 2\n\t\t\t\t\t|  |    |\n\t\t\t\t\t1  1    false\n\t\t */\n\t}\n}\n```\n\n## License\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\u003chttp://www.apache.org/licenses/LICENSE-2.0\u003e\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjkschneider%2Fjava-power-assert","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjkschneider%2Fjava-power-assert","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjkschneider%2Fjava-power-assert/lists"}