├── .github └── release-drafter.yml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .travis.yml ├── AUTHORS ├── CHANGELOG.md ├── LICENSE ├── README.md ├── gradletest ├── .gitignore ├── README.md ├── build.gradle ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle └── src │ └── test │ └── java │ └── TtyCheckTest.java ├── mvnw ├── mvnw.cmd ├── pom.xml ├── release ├── .gitignore ├── codesigning.asc.enc ├── deploy.sh └── settings.xml ├── screenshot.png └── src ├── main └── java │ └── org │ └── rnorth │ ├── TtyCheck.java │ ├── ansi │ ├── AnsiLite.java │ ├── CLib.java │ └── CapabilityDetection.java │ └── visibleassertions │ ├── AnsiSupport.java │ └── VisibleAssertions.java └── test └── java └── org └── rnorth ├── ansi └── AnsiLiteTest.java └── visibleassertions ├── DemoTest.java ├── TtyCheckTest.java └── VisibleAssertionsTest.java /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: $NEXT_PATCH_VERSION 🌈 2 | tag-template: $NEXT_PATCH_VERSION 3 | template: | 4 | ## Changes 5 | 6 | $CHANGES -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### JetBrains template 3 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion 4 | 5 | *.iml 6 | 7 | ## Directory-based project format: 8 | .idea/ 9 | # if you remove the above rule, at least ignore the following: 10 | 11 | # User-specific stuff: 12 | # .idea/workspace.xml 13 | # .idea/tasks.xml 14 | # .idea/dictionaries 15 | 16 | # Sensitive or high-churn files: 17 | # .idea/dataSources.ids 18 | # .idea/dataSources.xml 19 | # .idea/sqlDataSources.xml 20 | # .idea/dynamic.xml 21 | # .idea/uiDesigner.xml 22 | 23 | # Gradle: 24 | # .idea/gradle.xml 25 | # .idea/libraries 26 | 27 | # Mongo Explorer plugin: 28 | # .idea/mongoSettings.xml 29 | 30 | ## File-based project format: 31 | *.ipr 32 | *.iws 33 | 34 | ## Plugin-specific files: 35 | 36 | # IntelliJ 37 | /out/ 38 | 39 | # mpeltonen/sbt-idea plugin 40 | .idea_modules/ 41 | 42 | # JIRA plugin 43 | atlassian-ide-plugin.xml 44 | 45 | # Crashlytics plugin (for Android Studio and IntelliJ) 46 | com_crashlytics_export_strings.xml 47 | crashlytics.properties 48 | crashlytics-build.properties 49 | 50 | 51 | ### Maven template 52 | target/ 53 | pom.xml.tag 54 | pom.xml.releaseBackup 55 | pom.xml.versionsBackup 56 | pom.xml.next 57 | release.properties 58 | dependency-reduced-pom.xml 59 | buildNumber.properties 60 | .mvn/timing.properties 61 | 62 | 63 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rnorth/visible-assertions/ba7400caddf11538d96aad443fb74bbf1fc04c70/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.2/apache-maven-3.5.2-bin.zip -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - oraclejdk8 4 | 5 | env: 6 | global: 7 | - secure: "nzUookahVnilfJrnYKktFukYFe9uF1nGsM7QPD4gEChF21uCfxOYKh3UnDC1vXo+/F4aaln9/PgoNgu6rR705lU271t18d3Ux/uhJzBYq02IcnxXt1sjl9xyyA5iODVmzSYGwJpaHR8jjJ90g0mY3+Tdi/f1YKk3ttkv+HSB6E4rEyuKPySeS0iUOBCAQGqOli4K6pauQrn0ySBKIGNyuyT6KwAMrt3R+3RthvQqkXK3kEV/0mnvuj7827YDtksXzX7Zksjnjd4q8jBbEgj4WHRKZWBxaG02BosoQZgdF5AF5QZu5PhZ7S+tIs//FMQMsZZD3eZgMbcCf1sd57J7Oiexyq57go4ZfNkld/swF6EvzBaK08oIIl6qV/f80frorNFFQOCyP8dHIg7gY8QJIDcuYkf2vtAQlv45ogDJjRmwk72WuIwUtDr4AzbnhD6YqZZs9Hki3FvsMWkxiR0286smEApraS75kPQJ9ffg2O8cBdrVxbnTHcB3qZQ/SXx9g5r1IH3ID1b1JbRgQkXQXhfH2+8/t7jQG57vJlJdWi4fxbtxB44NXz8esLWhJDHLWoqbxJkvKUuuwATxwR9SGE7GHGMJYpxQzy0a1LSGecYWy/Bn9qSmEiDKUcSgy29I5WyjPc9/5C1CitnYWycfFc5IAFGGCUM790xKYeuY9fg=" 8 | - # ^^ OSSRH_JIRA_USERNAME 9 | - secure: "UZXbR7Hreiqs5hi/LotOzxqWGnXxhHkL4IjOodlppmG5zSieexlflcXTLKaWJI76TNh4u2RmtZTe23/kjVEyzRQqi++fYg6tkupcIjKKkgtVxKuTlzRnSjj4H0PpxNwwhOYh54dhIgtLGVpSt02qBF9ZgcmPL3aaoLg9/nTIBITL0TNzLr70T/6nUFDCgNjHrtiROrmfTbm36C/dQw2c3e2fIYXl44b9F/NDXlDf3HnKR8GpPIsFgCvoSyxkLa9X73jLOsrf7Tdco54MTRancws2mRX1+Nw63AwnFSCLFt/IZzpEVVnJ0/Gpu+86QpviHEvRmn8vJz1VJPGCdH4a8izCDxuko5208hyx0alKT2d5+y37+/sr0jiQS0ZkBoHhuOoHEPpEIDLdD0mgp3HZ+GlqGN4JD5DWkknSJc7JWLFvzNde54pbR4yi3Qa84E5Gz0l2r+HuenmrOA9ULbZsd5zKEyNsWnTzLINC5lerlaz3lR7qzUoj9dMqgS+RVzvyo8XR7m8+DgbajmozDzKeeGO8Ix67+Fg6IfUI79IjBJB6bZkkmZ7y+Qy59Am5yThW0P4fBVM5denF+8vXk03BReJqMiCLqV69txO3LM/qV7s6gSZIN+PwXFuK2iOgQfq5V57J34Ml/a3FyK9qLSakPRlc7oFAgrX+5qTwKLAtU00=" 10 | - # ^^ OSSRH_JIRA_PASSWORD 11 | - secure: "fSnMeha1iLIE6TsMJw5yCnRIWfs0HtMvkoTj4+73Oar3e4Nu0U0KRTTrYTaPl1WU1dbLrR4yaljz4SppwwIpzUom1JuqL/RbqA0jqSMw6DsIaqMUcx7Sku+5HVUTgAS3aBVQehlBkcvGZvI2vprwg4cvTRTq2+/4EOBrQzz60WeAdfgJR0Amm2eoWChEVBUEp5qrABu+5rOwfJWuMlFzgdSMSfhWzimA1i5RX3M4Xi4Du3LVl3krWMVxIFV+r79FBFWmJyWTDYmUla5jNMTyDtnt/0LHptnJp4rRCMZC3HbtpfnrO7r3tntz/U3uScJX+n2L1oThcTUyoES+A1RiuGa9z6h9cb9DlTTF7RewsEcNWAsDF/ssVXBmVg7XkJeevBJdnJUZZThSBmdNo6sGgqA64TOFGKQmbzXnTIdfZIaxGy5xskYb24DI+N6pIdRjgboG9k5E1eRw+n+plHBeFSMA3nLsExYmhjakIl6bA129QDkMEepQ27tUB38ds7tdc570KQjOWfIHzVsFcdp2kKVpEzozLG7s6WeSrqvwtWTk6UAK4Aed5bKINhqGWzR8nLvOAeBhJpveU9dAhelQ/XsnoqprZu2sucLzle4Yk/Me9y7XXlrRUiZD1m+GT8ewdrlPiMnaI+I+XKVZYULqo9NV0FNcKkkpi9QIQc+xV6Y=" 12 | - # ^^ GPG_KEY_NAME 13 | - secure: "SbA/QbPrr+F3hQv5/mGMtnKcmiV/2M04zgTDNXvBJe+r/4r1SYIeub3JZX3QYkVG7UIxxB3Pph5/OpvXDFq6x8scbLE9tgXSTVo/EtjQWtd5f1rC+DVipa5xO1kdwMOLNPcgxCWAh6v7HlUad7esKHWR0kGc8h/12G76UWc54Bs820/FKROMaYs4G2lTPxTYTTFRln+xQ0/pXDjbG9AIGue3WXQ0wlAB6HYmhvILSnF2UQAy1DLSmMAnLQspTjDD3h4Thwry6ymGbSWLCVB4jq2mWt1wM7iZyTSVh+xJdnVUvH7i3SlIX0zfkFOiNPHhjeTTKGNyC+DS76yhFe4KAyitEiZtKrNlE68X2Grd0uvwMHDzk/Y6QDlPayAnUK4KhH+g631ZthdovuuNgIefcPG+vpNqe7bjivb6/rUIi8s2/b2X/0rOqMrvIMSppJrou0qJ9ZOXIAu7H5YeBkI+3ib4yywfCNvSgo592fY00d9s0kk6hUdyZ8Q10kB2VqjVfXZxYPYU25WuyX7k7/BsjK/wsJ/xsCpdkSxiJjD7W+BzqFUgDEF9QLRsxIC8NKUEuzh8kRpHdzY9rcM623b90Z8BmBttQKZtYLRNz9UJsKLZiw881p6JMI0FxP3WK8ocp7PUgO1x3rNS6cgThuOufs0SoGeGT+xr9bGx5u8oImU=" 14 | - # ^^ GPG_PASSPHRASE 15 | 16 | install: ./mvnw install -P !build-extras -DskipTests=true -Dmaven.javadoc.skip=true -B -V 17 | 18 | script: 19 | - ./mvnw -P !build-extras install 20 | - pushd gradletest && ./gradlew test && popd 21 | 22 | deploy: 23 | provider: script 24 | script: release/deploy.sh 25 | on: 26 | tags: true 27 | branch: master 28 | 29 | cache: 30 | directories: 31 | - '$HOME/.m2/repository' 32 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Richard North -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | 2 | ## [2.1.1] - 2018-07-11 3 | 4 | * Bump JNA version 5 | 6 | ## [2.1.0] - 2017-11-11 7 | 8 | * Switch TTY detection to be based on JNA, for smaller dependency chain. Special case behaviour is in place for tests running in IntelliJ IDEA and Maven, which are both capable of correctly handling ANSI output even though there is not a TTY. 9 | 10 | ## [2.0.0] - 2017-07-13 11 | 12 | * Remove Jansi to reduce likelihood of native lib class conflicts when used in Gradle projects. ANSI output is implemented within the library now, with pnr-posix providing isatty support. 13 | * Allow system properties to be used to control visibility of output (see [README](README.md)). 14 | * Add `assertVisiblyEquals` and `assertRoughlyEquals` methods for approximate matching. 15 | 16 | ## [1.0.5] - 2016-04-28 17 | 18 | * Remove version ranges for dependencies and make versions explicit 19 | 20 | ## [1.0.4] - 2015-12-17 21 | 22 | * Improve output for equals assertions where objects are string-equal but different types 23 | * Improve output for equals assertions where either value is null 24 | 25 | ## [1.0.3] - 2015-08-28 26 | 27 | * Add assertThrows for Runnables as well as Callables 28 | 29 | ## [1.0.2] - 2015-08-03 30 | 31 | * Add assertNotEquals 32 | 33 | ## [1.0.1] - 2015-08-02 34 | 35 | * Initial release 36 | 37 | [2.1.1]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-2.1.1 38 | [2.1.0]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-2.1.0 39 | [2.0.0]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-2.0.0 40 | [1.0.4]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-1.0.4 41 | [1.0.3]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-1.0.3 42 | [1.0.2]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-1.0.2 43 | [1.0.1]: https://github.com/rnorth/visible-assertions/releases/tag/visible-assertions-1.0.1 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Richard North 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Visible Assertions 2 | 3 | > Alternative to JUnit assertions that provides a more insightful log narrative for your tests 4 | 5 | Screenshot showing example output 6 | 7 | [![Build Status](https://travis-ci.org/rnorth/visible-assertions.svg?branch=master)](https://travis-ci.org/rnorth/visible-assertions) 8 | 9 | 10 | ## Table of Contents 11 | 12 | 13 | - [Use Case](#use-case) 14 | - [Usage summary](#usage-summary) 15 | - [Simple assertions](#simple-assertions) 16 | - [Hamcrest](#hamcrest) 17 | - [assertThrows](#assertthrows) 18 | - [General test narrative](#general-test-narrative) 19 | - [Maven dependency](#maven-dependency) 20 | - [License](#license) 21 | - [Attributions](#attributions) 22 | - [Contributing](#contributing) 23 | - [Copyright](#copyright) 24 | 25 | 26 | 27 | ## Use Case 28 | 29 | Visible Assertions is designed to be used in place of the standard JUnit `Assert` class, providing an implementation of many of the core `assert*` methods. Each method takes an additional parameter which developers can use to describe exactly what the assertion is checking. 30 | 31 | The key difference is that every assertion is also accompanied by coloured and formatted log output which describes the progress of the tests in a fun, informative way. 32 | 33 | This helps with: 34 | 35 | * giving a useful description of which assertions passed/failed during a test run 36 | * 'comments as code' - your assertions provide a meaningful description of what they're doing, visible to both people looking at the code and those looking at the test output 37 | * through contextual markers, symbols* and use of colour**, it's quick to spot where tests have gone awry 38 | 39 | (* requires unicode support) 40 | 41 | (** coloured output requires a terminal that supports ANSI escape codes. If the terminal doesn't support ANSI, output will fall back to monochrome.) 42 | 43 | ## Usage summary 44 | 45 | ### Simple assertions 46 | 47 | A simple example: 48 | 49 | assertEquals("The sky is blue", Colours.BLUE, theSkyColour); 50 | 51 | yields: 52 | 53 |     ✔ The sky is blue 54 | 55 | unless it isn't: 56 | 57 |     ✘ The sky is blue
58 |         'PURPLE' does not equal expected 'BLUE' 59 | 60 | Additionally, when something is perhaps equivalent in value but not in type, additional output will provide a hint. 61 | This can be useful in cases where a simple type error has crept in to test code, e.g.: 62 | 63 |     ✘ The number of sales is returned correctly
64 |         '42' \[java.lang.Integer] does not equal expected '42' \[java.math.BigInteger] 65 | 66 | Other simple assertion methods provided are: 67 | 68 | * *assertTrue* 69 | * *assertFalse* 70 | * *assertNull* 71 | * *assertNotNull* 72 | * *assertNotEquals* 73 | * *assertSame* 74 | 75 | ### Hamcrest 76 | 77 | You can use Hamcrest matchers too: 78 | 79 | assertThat("the colour of the sky", sky.getColour(), is(equalTo(Colours.BLUE))); 80 | 81 | yields: 82 | 83 |     ✔ the colour of the sky is BLUE 84 | 85 | ### assertThrows 86 | 87 | If you want to assert that a block of code definitely does throw a particular class of assertion: 88 | 89 | assertThrows("it blows up if the input is out of range", IllegalArgumentException.class, () -> { 90 | account.withdraw(-1); 91 | }); 92 | 93 | This will fail if no exception is thrown or if the wrong type of exception is thrown. 94 | 95 | ### General test narrative 96 | 97 | While not strictly assertions, Visible Assertions also provides a handful of log-like methods to allow you to describe what's going on in each test: 98 | 99 | * *fail(String message)*: Just fail for a specified reason, which will be shown in red text. 100 | * *pass(String message)*: Indicate that some external check passed, with a message that will be shown in green. 101 | * *info(String message)*: Print a message with an 'info' symbol 102 | * *warn(String message)*: Print a message with a warning symbol, in yellow 103 | * *context(String message)*: Plots a message and horizontal line across the terminal to demarcate sections of a test 104 | 105 | ## Maven dependency 106 | 107 | 108 | org.rnorth.visible-assertions 109 | visible-assertions 110 | 2.0.0 111 | 112 | 113 | ## Controlling output 114 | 115 | Output may be controlled via system properties: 116 | 117 | * `visibleassertions.silence`: if set to `true`, assertions will still be enforced but no output will be produced. 118 | * `visibleassertions.silence.passes`: if set to `true`, assertion passes will not be output. 119 | * `visibleassertions.silence.failures`: if set to `true`, assertion failures will not be output. 120 | 121 | The library will attempt to detect terminal capabilities to determine whether it is appropriate to use ANSI (coloured) output. The basic logic is: 122 | 123 | * If STDOUT is a TTY, ANSI coloured output will be used. Otherwise, ANSI colour codes will only be output if: 124 | * running under Maven (latest versions of Maven will strip/preserve as appropriate) 125 | * running under IntelliJ IDEA 126 | 127 | If it is necessary to override this for some reason, the `visibleassertions.ansi.enabled` may be set: 128 | 129 | * `-Dvisibleassertions.ansi.enabled=true`: ANSI output will always be produced 130 | * `-Dvisibleassertions.ansi.enabled=false`: ANSI output will never be produced 131 | 132 | ## License 133 | 134 | See [LICENSE](LICENSE). 135 | 136 | ## Attributions 137 | 138 | This project is extracted from [TestPackage](http://testpackage.org) by the same author. 139 | 140 | ## Contributing 141 | 142 | * Star the project on Github and help spread the word :) 143 | * [Post an issue](https://github.com/rnorth/visible-assertions/issues) if you find any bugs 144 | * Contribute improvements or fixes using a [Pull Request](https://github.com/rnorth/visible-assertions/pulls). If you're going to contribute, thank you! Please just be sure to: 145 | * discuss with the authors on an issue ticket prior to doing anything big 146 | * follow the style, naming and structure conventions of the rest of the project 147 | * make commits atomic and easy to merge 148 | * verify all tests are passing. Build the project with `mvn clean install` to do this. 149 | 150 | ## Copyright 151 | 152 | Copyright (c) 2015-2017 Richard North. 153 | 154 | See [AUTHORS](AUTHORS) for contributors. 155 | -------------------------------------------------------------------------------- /gradletest/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Gradle template 3 | .gradle 4 | /build/ 5 | 6 | # Ignore Gradle GUI config 7 | gradle-app.setting 8 | 9 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 10 | !gradle-wrapper.jar 11 | 12 | # Cache of project 13 | .gradletasknamecache 14 | 15 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 16 | # gradle/wrapper/gradle-wrapper.properties 17 | 18 | -------------------------------------------------------------------------------- /gradletest/README.md: -------------------------------------------------------------------------------- 1 | This project is intended to help ensure consistent TTY detection when running under Gradle. 2 | 3 | Coloured output is not a goal for Gradle given that test STDOUT output is usually not displayed in the console. -------------------------------------------------------------------------------- /gradletest/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'java' 2 | 3 | // In this section you declare where to find the dependencies of your project 4 | repositories { 5 | mavenLocal() 6 | mavenCentral() 7 | } 8 | 9 | // In this section you declare the dependencies for your production and test code 10 | dependencies { 11 | compile 'org.slf4j:slf4j-api:1.7.25' 12 | compile 'org.rnorth.visible-assertions:visible-assertions:0-SNAPSHOT' 13 | 14 | testCompile 'org.fusesource.jansi:jansi:1.11' 15 | testCompile 'junit:junit:4.12' 16 | } 17 | 18 | -------------------------------------------------------------------------------- /gradletest/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rnorth/visible-assertions/ba7400caddf11538d96aad443fb74bbf1fc04c70/gradletest/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradletest/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sat Nov 11 17:10:40 GMT 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-all.zip 7 | -------------------------------------------------------------------------------- /gradletest/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradletest/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /gradletest/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'gradletest' 2 | -------------------------------------------------------------------------------- /gradletest/src/test/java/TtyCheckTest.java: -------------------------------------------------------------------------------- 1 | import org.fusesource.jansi.internal.CLibrary; 2 | import org.junit.Test; 3 | import org.rnorth.ansi.CapabilityDetection; 4 | 5 | import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; 6 | import static org.rnorth.visibleassertions.VisibleAssertions.info; 7 | 8 | public class TtyCheckTest { 9 | 10 | @Test 11 | public void checkConsistentTtyDetection() { 12 | info("isTty=" + CapabilityDetection.isTty()); 13 | info("isUnderMaven=" + CapabilityDetection.isUnderMaven()); 14 | info("isUnderIDEA=" + CapabilityDetection.isUnderIDEA()); 15 | 16 | assertEquals("JNA and Jansi detect tty the same", 17 | CapabilityDetection.isTty() ? 1 : 0, 18 | CLibrary.isatty(1)); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Mingw, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | if [ "$MVNW_VERBOSE" = true ]; then 205 | echo $MAVEN_PROJECTBASEDIR 206 | fi 207 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 208 | 209 | # For Cygwin, switch paths to Windows format before running java 210 | if $cygwin; then 211 | [ -n "$M2_HOME" ] && 212 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 213 | [ -n "$JAVA_HOME" ] && 214 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 215 | [ -n "$CLASSPATH" ] && 216 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 217 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 218 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 219 | fi 220 | 221 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 222 | 223 | exec "$JAVACMD" \ 224 | $MAVEN_OPTS \ 225 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 226 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 227 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 228 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM set title of command window 39 | title %0 40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 42 | 43 | @REM set %HOME% to equivalent of $HOME 44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 45 | 46 | @REM Execute a user defined script before this one 47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 51 | :skipRcPre 52 | 53 | @setlocal 54 | 55 | set ERROR_CODE=0 56 | 57 | @REM To isolate internal variables from possible post scripts, we use another setlocal 58 | @setlocal 59 | 60 | @REM ==== START VALIDATION ==== 61 | if not "%JAVA_HOME%" == "" goto OkJHome 62 | 63 | echo. 64 | echo Error: JAVA_HOME not found in your environment. >&2 65 | echo Please set the JAVA_HOME variable in your environment to match the >&2 66 | echo location of your Java installation. >&2 67 | echo. 68 | goto error 69 | 70 | :OkJHome 71 | if exist "%JAVA_HOME%\bin\java.exe" goto init 72 | 73 | echo. 74 | echo Error: JAVA_HOME is set to an invalid directory. >&2 75 | echo JAVA_HOME = "%JAVA_HOME%" >&2 76 | echo Please set the JAVA_HOME variable in your environment to match the >&2 77 | echo location of your Java installation. >&2 78 | echo. 79 | goto error 80 | 81 | @REM ==== END VALIDATION ==== 82 | 83 | :init 84 | 85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 86 | @REM Fallback to current working directory if not found. 87 | 88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 90 | 91 | set EXEC_DIR=%CD% 92 | set WDIR=%EXEC_DIR% 93 | :findBaseDir 94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 95 | cd .. 96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 97 | set WDIR=%CD% 98 | goto findBaseDir 99 | 100 | :baseDirFound 101 | set MAVEN_PROJECTBASEDIR=%WDIR% 102 | cd "%EXEC_DIR%" 103 | goto endDetectBaseDir 104 | 105 | :baseDirNotFound 106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 107 | cd "%EXEC_DIR%" 108 | 109 | :endDetectBaseDir 110 | 111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 112 | 113 | @setlocal EnableExtensions EnableDelayedExpansion 114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 116 | 117 | :endReadAdditionalConfig 118 | 119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 120 | 121 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 122 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 123 | 124 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 125 | if ERRORLEVEL 1 goto error 126 | goto end 127 | 128 | :error 129 | set ERROR_CODE=1 130 | 131 | :end 132 | @endlocal & set ERROR_CODE=%ERROR_CODE% 133 | 134 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 135 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 136 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 137 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 138 | :skipRcPost 139 | 140 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 141 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 142 | 143 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 144 | 145 | exit /B %ERROR_CODE% 146 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | org.rnorth.visible-assertions 7 | visible-assertions 8 | 0-SNAPSHOT 9 | 10 | 11 | Visible Assertions 12 | 13 | Richer logging for Java test suites 14 | 15 | https://github.com/rnorth/visible-assertions 16 | 17 | 18 | MIT 19 | http://opensource.org/licenses/MIT 20 | 21 | 22 | 23 | 24 | rnorth 25 | Richard North 26 | rich.north@gmail.com 27 | 28 | 29 | 30 | 31 | 32 | junit 33 | junit 34 | 4.12 35 | provided 36 | 37 | 38 | 39 | 40 | org.fusesource.jansi 41 | jansi 42 | 1.17.1 43 | test 44 | 45 | 46 | 47 | net.java.dev.jna 48 | jna 49 | 5.2.0 50 | 51 | 52 | 53 | 54 | 55 | 56 | maven-compiler-plugin 57 | 3.8.1 58 | 59 | 1.7 60 | 1.7 61 | 62 | 63 | 64 | maven-scm-plugin 65 | 1.11.2 66 | 67 | ${project.version} 68 | 69 | 70 | 71 | org.sonatype.plugins 72 | nexus-staging-maven-plugin 73 | 1.6.8 74 | true 75 | 76 | ossrh 77 | https://oss.sonatype.org/ 78 | true 79 | 80 | 81 | 82 | maven-javadoc-plugin 83 | 3.0.1 84 | 85 | 86 | attach-javadocs 87 | 88 | jar 89 | 90 | 91 | 92 | 93 | 94 | org.codehaus.mojo 95 | animal-sniffer-maven-plugin 96 | 1.17 97 | 98 | 99 | signature-check 100 | verify 101 | 102 | check 103 | 104 | 105 | 106 | 107 | 108 | org.codehaus.mojo.signature 109 | java17 110 | 1.0 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | scm:git:https://github.com/rnorth/visible-assertions.git 119 | scm:git:git@github.com:rnorth/visible-assertions.git 120 | https://github.com/rnorth/visible-assertions 121 | HEAD 122 | 123 | 124 | 125 | 126 | sign 127 | 128 | 129 | 130 | org.apache.maven.plugins 131 | maven-gpg-plugin 132 | 1.6 133 | 134 | 135 | sign-artifacts 136 | verify 137 | 138 | sign 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | build-extras 149 | 150 | true 151 | 152 | 153 | 154 | 155 | org.apache.maven.plugins 156 | maven-source-plugin 157 | 3.0.1 158 | 159 | 160 | attach-sources 161 | 162 | jar-no-fork 163 | 164 | 165 | 166 | 167 | 168 | org.apache.maven.plugins 169 | maven-javadoc-plugin 170 | 3.0.1 171 | 172 | 173 | attach-javadocs 174 | 175 | jar 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | -------------------------------------------------------------------------------- /release/.gitignore: -------------------------------------------------------------------------------- 1 | codesigning.asc 2 | -------------------------------------------------------------------------------- /release/codesigning.asc.enc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rnorth/visible-assertions/ba7400caddf11538d96aad443fb74bbf1fc04c70/release/codesigning.asc.enc -------------------------------------------------------------------------------- /release/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -x 4 | 5 | openssl aes-256-cbc -K $encrypted_99aebaea6bf8_key -iv $encrypted_99aebaea6bf8_iv -in release/codesigning.asc.enc -out release/codesigning.asc -d 6 | gpg --fast-import release/codesigning.asc 7 | 8 | ./mvnw versions:set -DnewVersion=$TRAVIS_TAG 9 | ./mvnw deploy -P sign,build-extras,!test-only -DskipTests --settings release/settings.xml 10 | -------------------------------------------------------------------------------- /release/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ossrh 5 | ${env.OSSRH_JIRA_USERNAME} 6 | ${env.OSSRH_JIRA_PASSWORD} 7 | 8 | 9 | 10 | 11 | 12 | ossrh 13 | 14 | true 15 | 16 | 17 | gpg 18 | ${env.GPG_KEY_NAME} 19 | ${env.GPG_PASSPHRASE} 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rnorth/visible-assertions/ba7400caddf11538d96aad443fb74bbf1fc04c70/screenshot.png -------------------------------------------------------------------------------- /src/main/java/org/rnorth/TtyCheck.java: -------------------------------------------------------------------------------- 1 | package org.rnorth; 2 | 3 | import org.rnorth.ansi.CapabilityDetection; 4 | 5 | import static org.rnorth.ansi.AnsiLite.green; 6 | import static org.rnorth.visibleassertions.VisibleAssertions.info; 7 | 8 | /** 9 | * Simple class for manual testing (direct execution) 10 | */ 11 | public class TtyCheck { 12 | 13 | public static void main(String[] args) { 14 | info("isTty=" + CapabilityDetection.isTty()); 15 | info("isUnderMaven=" + CapabilityDetection.isUnderMaven()); 16 | info("isUnderIDEA=" + CapabilityDetection.isUnderIDEA()); 17 | 18 | System.out.println(green("This text will be green if ANSI output is enabled")); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/rnorth/ansi/AnsiLite.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.ansi; 2 | 3 | import static org.rnorth.ansi.CapabilityDetection.isTty; 4 | import static org.rnorth.ansi.CapabilityDetection.isUnderIDEA; 5 | import static org.rnorth.ansi.CapabilityDetection.isUnderMaven; 6 | 7 | /** 8 | * A simple ANSI colour output formatter. It is quite simplistic in implementation, and less efficient than it could be. 9 | * 10 | * It does, however, work, and is easy to use. 11 | */ 12 | public class AnsiLite { 13 | 14 | // Color code strings from: 15 | // http://www.topmudsites.com/forums/mud-coding/413-java-ansi.html 16 | static final String RESET = "\u001B[0m"; 17 | 18 | static final String HIGH_INTENSITY = "\u001B[1m"; 19 | static final String LOW_INTENSITY = "\u001B[2m"; 20 | static final String REVERSE_VIDEO = "\u001B[7m"; 21 | 22 | static final String UNDERLINE = "\u001B[4m"; 23 | 24 | static final String BLACK = "\u001B[30m"; 25 | static final String RED = "\u001B[31m"; 26 | static final String GREEN = "\u001B[32m"; 27 | static final String YELLOW = "\u001B[33m"; 28 | static final String BLUE = "\u001B[34m"; 29 | static final String MAGENTA = "\u001B[35m"; 30 | static final String CYAN = "\u001B[36m"; 31 | static final String WHITE = "\u001B[37m"; 32 | 33 | static final String BACKGROUND_BLACK = "\u001B[40m"; 34 | static final String BACKGROUND_RED = "\u001B[41m"; 35 | static final String BACKGROUND_GREEN = "\u001B[42m"; 36 | static final String BACKGROUND_YELLOW = "\u001B[43m"; 37 | static final String BACKGROUND_BLUE = "\u001B[44m"; 38 | static final String BACKGROUND_MAGENTA = "\u001B[45m"; 39 | static final String BACKGROUND_CYAN = "\u001B[46m"; 40 | static final String BACKGROUND_WHITE = "\u001B[47m"; 41 | 42 | private final String code; 43 | private final Object[] s; 44 | 45 | private AnsiLite(String code, Object... s) { 46 | this.code = code; 47 | this.s = s; 48 | } 49 | 50 | public static AnsiLite underline(Object... s) { 51 | return new AnsiLite(UNDERLINE, s); 52 | } 53 | 54 | public static AnsiLite black(Object... s) { 55 | return new AnsiLite(BLACK, s); 56 | } 57 | 58 | public static AnsiLite red(Object... s) { 59 | return new AnsiLite(RED, s); 60 | } 61 | 62 | public static AnsiLite green(Object... s) { 63 | return new AnsiLite(GREEN, s); 64 | } 65 | 66 | public static AnsiLite yellow(Object... s) { 67 | return new AnsiLite(YELLOW, s); 68 | } 69 | 70 | public static AnsiLite blue(Object... s) { 71 | return new AnsiLite(BLUE, s); 72 | } 73 | 74 | public static AnsiLite magenta(Object... s) { 75 | return new AnsiLite(MAGENTA, s); 76 | } 77 | 78 | public static AnsiLite cyan(Object... s) { 79 | return new AnsiLite(CYAN, s); 80 | } 81 | 82 | public static AnsiLite white(Object... s) { 83 | return new AnsiLite(WHITE, s); 84 | } 85 | 86 | public static AnsiLite bgBlack(Object... s) { 87 | return new AnsiLite(BACKGROUND_BLACK, s); 88 | } 89 | 90 | public static AnsiLite bgRed(Object... s) { 91 | return new AnsiLite(BACKGROUND_RED, s); 92 | } 93 | 94 | public static AnsiLite bgGreen(Object... s) { 95 | return new AnsiLite(BACKGROUND_GREEN, s); 96 | } 97 | 98 | public static AnsiLite bgYellow(Object... s) { 99 | return new AnsiLite(BACKGROUND_YELLOW, s); 100 | } 101 | 102 | public static AnsiLite bgBlue(Object... s) { 103 | return new AnsiLite(BACKGROUND_BLUE, s); 104 | } 105 | 106 | public static AnsiLite bgMagenta(Object... s) { 107 | return new AnsiLite(BACKGROUND_MAGENTA, s); 108 | } 109 | 110 | public static AnsiLite bgCyan(Object... s) { 111 | return new AnsiLite(BACKGROUND_CYAN, s); 112 | } 113 | 114 | public static AnsiLite bgWhite(Object... s) { 115 | return new AnsiLite(BACKGROUND_WHITE, s); 116 | } 117 | 118 | public static AnsiLite bright(Object... s) { 119 | return new AnsiLite(HIGH_INTENSITY, s); 120 | } 121 | 122 | public static AnsiLite dim(Object... s) { 123 | return new AnsiLite(LOW_INTENSITY, s); 124 | } 125 | 126 | public static AnsiLite reverse(Object... s) { 127 | return new AnsiLite(REVERSE_VIDEO, s); 128 | } 129 | 130 | @Override 131 | public String toString() { 132 | final StringBuilder sb = new StringBuilder(); 133 | for (Object o : this.s) { 134 | if (isEnabled()) { 135 | sb.append(this.code); 136 | sb.append(o); 137 | sb.append(RESET); 138 | } else { 139 | sb.append(o); 140 | } 141 | } 142 | return sb.toString(); 143 | } 144 | 145 | private boolean isEnabled() { 146 | 147 | /* Allow ANSI support to be forced on or off (by setting -Dvisibleassertions.ansi.enabled=true|false) */ 148 | if (System.getProperty("visibleassertions.ansi.enabled") != null) { 149 | return Boolean.getBoolean("visibleassertions.ansi.enabled"); 150 | } 151 | 152 | /* Emulate behaviour of Jansi library for compatibility */ 153 | if (Boolean.getBoolean("jansi.strip")) { 154 | return false; 155 | } 156 | 157 | if (Boolean.getBoolean("jansi.passthrough")) { 158 | return true; 159 | } 160 | 161 | if (Boolean.getBoolean("ansi.passthrough")) { 162 | return true; 163 | } 164 | 165 | if (Boolean.getBoolean("jansi.force")) { 166 | return true; 167 | } 168 | 169 | return isUnderIDEA() || isUnderMaven() || isTty(); 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /src/main/java/org/rnorth/ansi/CLib.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.ansi; 2 | 3 | import com.sun.jna.Library; 4 | import com.sun.jna.Native; 5 | 6 | /** 7 | * JNA accessor for native CLib. 8 | */ 9 | interface CLib extends Library { 10 | CLib INSTANCE = (CLib) Native.loadLibrary("c", CLib.class); 11 | 12 | int isatty(int fd); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/org/rnorth/ansi/CapabilityDetection.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.ansi; 2 | 3 | import com.sun.jna.Platform; 4 | 5 | /** 6 | * Simple terminal capability detection. 7 | */ 8 | public class CapabilityDetection { 9 | private static final int STDOUT_FILENO = 1; 10 | 11 | private CapabilityDetection() { 12 | // Utility class - don't allow construction; 13 | } 14 | 15 | public static boolean isUnderIDEA() { 16 | // Rough check for whether or not we're running in IDEA 17 | String classPath = System.getProperty("java.class.path"); 18 | return classPath.contains("idea_rt.jar"); 19 | } 20 | 21 | public static boolean isUnderMaven() { 22 | // Rough check for whether or not we're running in a Maven build 23 | return findClass("org.apache.maven.surefire.booter.ForkedBooter") || 24 | findClass("org.codehaus.plexus.classworlds.launcher.Launcher"); 25 | } 26 | 27 | private static boolean findClass(String className) { 28 | try { 29 | Class.forName(className); 30 | return true; 31 | } catch (Exception ignored) { 32 | return false; 33 | } 34 | } 35 | 36 | public static boolean isTty() { 37 | // Don't attempt to check on Windows 38 | if (Platform.isWindows()) { 39 | return false; 40 | } 41 | 42 | // Check native isatty using JNA. If we fail for any reason, assume no TTY and carry on. 43 | try { 44 | return CLib.INSTANCE.isatty(STDOUT_FILENO) != 0; 45 | } catch (Throwable ignored) { 46 | return false; 47 | } 48 | } 49 | 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/org/rnorth/visibleassertions/AnsiSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Deloitte Digital and Richard North 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.rnorth.visibleassertions; 18 | 19 | /** 20 | * @author rnorth 21 | */ 22 | class AnsiSupport { 23 | 24 | static int terminalWidth() { 25 | // TODO: lookup via stty on *nix 26 | return 80; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/org/rnorth/visibleassertions/VisibleAssertions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Deloitte Digital and Richard North 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.rnorth.visibleassertions; 18 | 19 | import org.hamcrest.Description; 20 | import org.hamcrest.Matcher; 21 | import org.hamcrest.StringDescription; 22 | 23 | import java.util.concurrent.Callable; 24 | 25 | import static org.rnorth.ansi.AnsiLite.*; 26 | 27 | /** 28 | * Assertions for use in Java tests, with contextual information on each assertion performed. 29 | *

30 | * Output is to stdout, and is coloured if the terminal supports it. 31 | * 32 | * @author rnorth 33 | */ 34 | public class VisibleAssertions extends AnsiSupport { 35 | 36 | private static final String TICK_MARK = "\u2714"; 37 | private static final String CROSS_MARK = "\u2718"; 38 | private static final String INFO_MARK = "\u2139\ufe0e"; 39 | private static final String WARN_MARK = "\u26a0\ufe0e"; 40 | private static final String CONTEXT_MARK = "\u2508"; 41 | 42 | // Utility class, hidden constructor 43 | protected VisibleAssertions() { 44 | 45 | } 46 | 47 | /** 48 | * Log an informational message. 49 | *

50 | * The output will be in white, following an 'i' symbol. 51 | * 52 | * @param message message to output 53 | */ 54 | public static void info(String message) { 55 | if (Boolean.getBoolean("visibleassertions.silence")) { 56 | return; 57 | } 58 | 59 | System.out.println(" " + white(bright(INFO_MARK + " " + message))); 60 | } 61 | 62 | /** 63 | * Log a warning message. 64 | *

65 | * The output will be in yellow, following a '!' symbol. 66 | * 67 | * @param message message to output 68 | */ 69 | public static void warn(String message) { 70 | if (Boolean.getBoolean("visibleassertions.silence")) { 71 | return; 72 | } 73 | 74 | System.out.println(" " + yellow(bright(WARN_MARK + " " + message))); 75 | } 76 | 77 | /** 78 | * Log a contextual message, in the style of a 'dividing line' in the test output. 79 | *

80 | * The output will be in grey, surrounded by a horizontal line the full width of the current terminal (or 80 chars). 81 | * 82 | * @param context contextual message to output. 83 | */ 84 | public static void context(CharSequence context) { 85 | context(context, 0); 86 | } 87 | 88 | /** 89 | * Log a contextual message, in the style of a 'dividing line' in the test output. 90 | *

91 | * The output will be in grey, surrounded by a horizontal line the full width of the current terminal (or 80 chars). 92 | * 93 | * @param context contextual message to output 94 | * @param indent number of space characters to indent this line by 95 | */ 96 | public static void context(CharSequence context, int indent) { 97 | if (Boolean.getBoolean("visibleassertions.silence")) { 98 | return; 99 | } 100 | 101 | StringBuilder sb = new StringBuilder(); 102 | for (int i = 0; i < indent; i++) sb.append(" "); 103 | for (int i = 0; i < 4; i++) sb.append(CONTEXT_MARK); 104 | 105 | sb.append(" "); 106 | sb.append(context); 107 | 108 | int terminalWidth = terminalWidth(); 109 | sb.append(" "); 110 | for (int i = sb.length(); i < terminalWidth; i++) { 111 | sb.append(CONTEXT_MARK); 112 | } 113 | 114 | System.out.println(dim(sb.toString())); 115 | } 116 | 117 | /** 118 | * Assert that a value is true. 119 | *

120 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 121 | * 122 | * @param message message to display alongside the assertion outcome 123 | * @param value value to test 124 | */ 125 | public static void assertTrue(String message, boolean value) { 126 | if (value) { 127 | pass(message); 128 | } else { 129 | fail(message, null); 130 | } 131 | } 132 | 133 | /** 134 | * Assert that a value is false. 135 | *

136 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 137 | * 138 | * @param message message to display alongside the assertion outcome 139 | * @param value value to test 140 | */ 141 | public static void assertFalse(String message, boolean value) { 142 | if (!value) { 143 | pass(message); 144 | } else { 145 | fail(message, null); 146 | } 147 | } 148 | 149 | /** 150 | * Assert that an actual value is equal to an expected value. 151 | *

152 | * Equality is tested with the standard Object equals() method, unless both values are null. 153 | *

154 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 155 | * 156 | * @param message message to display alongside the assertion outcome 157 | * @param expected the expected value 158 | * @param actual the actual value 159 | */ 160 | public static void assertEquals(String message, Object expected, Object actual) { 161 | 162 | String expectedInQuotes = inQuotesIfNotNull(expected); 163 | String actualInQuotes = inQuotesIfNotNull(actual); 164 | 165 | if (areBothNull(expected, actual)) { 166 | pass(message); 167 | } else if (isObjectEquals(expected, actual)) { 168 | pass(message); 169 | } else if (isObjectStringEqualsButDifferentType(expected, actual)) { 170 | String actualClass = actual.getClass().getCanonicalName(); 171 | String expectedClass = expected.getClass().getCanonicalName(); 172 | fail(message, actualInQuotes + " [" + actualClass + "] does not equal expected " + expectedInQuotes + " [" + expectedClass + "]"); 173 | } else { 174 | fail(message, actualInQuotes + " does not equal expected " + expectedInQuotes); 175 | } 176 | } 177 | 178 | /** 179 | * Assert that an actual value is visibly equal to an expected value, following conversion to a String via toString(). 180 | *

181 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 182 | * 183 | * @param message message to display alongside the assertion outcome 184 | * @param expected the expected value 185 | * @param actual the actual value 186 | */ 187 | public static void assertVisiblyEquals(String message, Object expected, Object actual) { 188 | 189 | String expectedInQuotes = inQuotesIfNotNull(expected); 190 | String actualInQuotes = inQuotesIfNotNull(actual); 191 | 192 | if (areBothNull(expected, actual)) { 193 | pass(message); 194 | } else if (isObjectEquals(String.valueOf(expected), String.valueOf(actual))) { 195 | pass(message); 196 | } else { 197 | fail(message, actualInQuotes + " after toString() does not equal expected " + expectedInQuotes); 198 | } 199 | } 200 | 201 | /** 202 | * Assert that an actual value is approximately equal to an expected value - determined by whether the difference 203 | * between the two values is less than a provided epsilon value. 204 | *

205 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 206 | * 207 | * @param message message to display alongside the assertion outcome 208 | * @param expected the expected value 209 | * @param actual the actual value 210 | * @param epsilon the allowable absolute difference between expected and actual values 211 | */ 212 | public static void assertRoughlyEquals(String message, Double expected, Double actual, Double epsilon) { 213 | 214 | String expectedInQuotes = inQuotesIfNotNull(expected); 215 | String actualInQuotes = inQuotesIfNotNull(actual); 216 | 217 | if (areBothNull(expected, actual)) { 218 | pass(message); 219 | } else if (Math.abs(actual - expected) < epsilon) { 220 | pass(message); 221 | } else { 222 | fail(message, actualInQuotes + " differs from expected " + expectedInQuotes + " by more than allowed amount (" + epsilon + ")"); 223 | } 224 | } 225 | 226 | /** 227 | * Assert that an actual value is not equal to an expected value. 228 | *

229 | * Equality is tested with the standard Object equals() method, unless both values are null. 230 | *

231 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 232 | * 233 | * @param message message to display alongside the assertion outcome 234 | * @param expected the expected value 235 | * @param actual the actual value 236 | */ 237 | public static void assertNotEquals(String message, Object expected, Object actual) { 238 | if (areBothNull(expected, actual)) { 239 | fail(message); 240 | } else if (isObjectEquals(expected, actual)) { 241 | fail(message); 242 | } else { 243 | pass(message); 244 | } 245 | } 246 | 247 | private static boolean areBothNull(Object expected, Object actual) { 248 | return expected == null && actual == null; 249 | } 250 | 251 | private static boolean isObjectEquals(Object expected, Object actual) { 252 | return expected != null && expected.equals(actual); 253 | } 254 | 255 | private static boolean isObjectStringEqualsButDifferentType(Object expected, Object actual) { 256 | 257 | if (expected == null || actual == null) { 258 | return false; 259 | } 260 | 261 | String expectedAsString = String.valueOf(expected); 262 | String actualAsString = String.valueOf(actual); 263 | 264 | return actualAsString.equals(expectedAsString); 265 | } 266 | 267 | private static String inQuotesIfNotNull(Object value) { 268 | return value == null ? "null" : "'" + String.valueOf(value) + "'"; 269 | } 270 | 271 | /** 272 | * Assert that a value is null. 273 | *

274 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 275 | * 276 | * @param message message to display alongside the assertion outcome 277 | * @param o value to test 278 | */ 279 | public static void assertNull(String message, Object o) { 280 | if (o == null) { 281 | pass(message); 282 | } else { 283 | fail(message, "'" + o + "' is not null"); 284 | } 285 | } 286 | 287 | /** 288 | * Assert that a value is not null. 289 | *

290 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 291 | * 292 | * @param message message to display alongside the assertion outcome 293 | * @param o value to test 294 | */ 295 | public static void assertNotNull(String message, Object o) { 296 | if (o != null) { 297 | pass(message); 298 | } else { 299 | fail(message, null); 300 | } 301 | } 302 | 303 | /** 304 | * Assert that an actual value is the same object as an expected value. 305 | *

306 | * Sameness is tested with the == operator. 307 | *

308 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 309 | * 310 | * @param message message to display alongside the assertion outcome 311 | * @param expected the expected value 312 | * @param actual the actual value 313 | */ 314 | public static void assertSame(String message, Object expected, Object actual) { 315 | 316 | String expectedInQuotes = inQuotesIfNotNull(expected); 317 | String actualInQuotes = inQuotesIfNotNull(actual); 318 | 319 | if (expected == actual) { 320 | pass(message); 321 | } else { 322 | fail(message, actualInQuotes + " is not the same (!=) as expected " + expectedInQuotes); 323 | } 324 | } 325 | 326 | /** 327 | * Just fail with an AssertionError, citing a given message. 328 | *

329 | * A red cross will be shown. 330 | * 331 | * @param message message to display alongside the red cross 332 | */ 333 | public static void fail(String message) { 334 | fail(message, null); 335 | } 336 | 337 | /** 338 | * Assert using a Hamcrest matcher. 339 | * 340 | * @param whatTheObjectIs what is the thing being tested, in a logical sense 341 | * @param actual the actual value 342 | * @param matcher a matcher to check the actual value against 343 | * @param class of the actual value 344 | */ 345 | public static void assertThat(String whatTheObjectIs, T actual, Matcher matcher) { 346 | Description description = new StringDescription(); 347 | if (matcher.matches(actual)) { 348 | description.appendText(whatTheObjectIs); 349 | description.appendText(" "); 350 | matcher.describeTo(description); 351 | pass(description.toString()); 352 | } else { 353 | description.appendText("asserted that it ") 354 | .appendDescriptionOf(matcher) 355 | .appendText(" but "); 356 | matcher.describeMismatch(actual, description); 357 | fail("assertion on " + whatTheObjectIs + " failed", description.toString()); 358 | } 359 | } 360 | 361 | /** 362 | * Assert that a given callable throws an exception of a particular class. 363 | *

364 | * The assertion passes if the callable throws exactly the same class of exception (not a subclass). 365 | *

366 | * If the callable doesn't throw an exception at all, or if another class of exception is thrown, the assertion 367 | * fails. 368 | *

369 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 370 | * 371 | * @param message message to display alongside the assertion outcome 372 | * @param exceptionClass the expected exception class 373 | * @param callable a Callable to invoke 374 | * @param return type of the callable 375 | */ 376 | public static void assertThrows(String message, Class exceptionClass, Callable callable) { 377 | T result; 378 | try { 379 | result = callable.call(); 380 | fail(message, "No exception was thrown (expected " + exceptionClass.getSimpleName() + " but '" + result + "' was returned instead)"); 381 | } catch (Exception e) { 382 | if (!e.getClass().equals(exceptionClass)) { 383 | fail(message, e.getClass().getSimpleName() + " was thrown instead of " + exceptionClass.getSimpleName()); 384 | } 385 | } 386 | 387 | pass(message); 388 | } 389 | 390 | /** 391 | * Assert that a given runnable throws an exception of a particular class. 392 | *

393 | * The assertion passes if the runnable throws exactly the same class of exception (not a subclass). 394 | *

395 | * If the runnable doesn't throw an exception at all, or if another class of exception is thrown, the assertion 396 | * fails. 397 | *

398 | * If the assertion passes, a green tick will be shown. If the assertion fails, a red cross will be shown. 399 | * 400 | * @param message message to display alongside the assertion outcome 401 | * @param exceptionClass the expected exception class 402 | * @param runnable a Runnable to invoke 403 | */ 404 | public static void assertThrows(String message, Class exceptionClass, Runnable runnable) { 405 | try { 406 | runnable.run(); 407 | fail(message, "No exception was thrown (expected " + exceptionClass.getSimpleName() + ")"); 408 | } catch (Exception e) { 409 | if (!e.getClass().equals(exceptionClass)) { 410 | fail(message, e.getClass().getSimpleName() + " was thrown instead of " + exceptionClass.getSimpleName()); 411 | } 412 | } 413 | 414 | pass(message); 415 | } 416 | 417 | /** 418 | * Indicate that something passed. 419 | * 420 | * @param message message to display alongside a green tick 421 | */ 422 | public static void pass(String message) { 423 | if (Boolean.getBoolean("visibleassertions.silence") || Boolean.getBoolean("visibleassertions.silence.passes")) { 424 | return; 425 | } 426 | System.out.println(" " + green(TICK_MARK + " " + message)); 427 | } 428 | 429 | public static void fail(String message, String hint) { 430 | if (Boolean.getBoolean("visibleassertions.silence") || Boolean.getBoolean("visibleassertions.silence.failures")) { 431 | return; 432 | } 433 | 434 | System.out.println(" " + red(CROSS_MARK + " " + message)); 435 | 436 | if (hint == null) { 437 | throw new AssertionError(message); 438 | } else { 439 | System.out.println(" " + yellow(hint)); 440 | throw new AssertionError(message + ": " + hint); 441 | } 442 | 443 | } 444 | } 445 | -------------------------------------------------------------------------------- /src/test/java/org/rnorth/ansi/AnsiLiteTest.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.ansi; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import static org.rnorth.ansi.AnsiLite.*; 8 | import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; 9 | 10 | /** 11 | * TODO: Javadocs 12 | */ 13 | public class AnsiLiteTest { 14 | @Before 15 | public void setUp() throws Exception { 16 | System.setProperty("jansi.force", "true"); 17 | } 18 | 19 | @Test 20 | public void simpleTest() { 21 | final String text = red("Hello world").toString(); 22 | assertEquals("codes can be used as strings", 23 | RED + "Hello world" + RESET, 24 | text); 25 | } 26 | 27 | @Test 28 | public void nestingTest() { 29 | final String text = blue(underline("Hello world")).toString(); 30 | assertEquals("codes can be nested", 31 | BLUE + UNDERLINE + "Hello world" + RESET + RESET, 32 | text); 33 | } 34 | 35 | @Test 36 | public void complexNestingTest() { 37 | final String text = green("Hello ", underline("world"), " again").toString(); 38 | assertEquals("codes can be nested in a complex way", 39 | GREEN + "Hello " + RESET + GREEN + UNDERLINE + "world" + RESET + RESET + GREEN + " again" + RESET, 40 | text); 41 | } 42 | 43 | @After 44 | public void tearDown() throws Exception { 45 | System.setProperty("jansi.force", "false"); 46 | } 47 | 48 | } -------------------------------------------------------------------------------- /src/test/java/org/rnorth/visibleassertions/DemoTest.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.visibleassertions; 2 | 3 | import org.junit.Rule; 4 | import org.junit.Test; 5 | import org.junit.rules.TestWatcher; 6 | import org.junit.runner.Description; 7 | 8 | import static org.rnorth.visibleassertions.VisibleAssertions.*; 9 | 10 | /** 11 | * This test doesn't actually do much, and doesn't have a real system under test. 12 | * 13 | * It is intended to show a few ways of using the VisibleAssertions.* methods. 14 | */ 15 | public class DemoTest { 16 | 17 | private boolean shouldFail = false; 18 | 19 | @Rule 20 | public TestWatcher testWatcher = new TestWatcher() { 21 | @Override 22 | protected void starting(Description description) { 23 | context(description.getMethodName()); 24 | } 25 | }; 26 | 27 | @Test 28 | public void testSuccessfulLoginAndAccessToCart() throws InterruptedException { 29 | 30 | info("Attempting login as testuser, password: opensesame"); 31 | 32 | assertTrue("Clicking 'login' takes the user to the next page", true); 33 | 34 | assertEquals("The welcome screen shows the user's name", "John Doe", "John Doe"); 35 | 36 | info("Navigating to the cart page"); 37 | 38 | int itemsInCart = shouldFail ? 2 : 0; 39 | assertEquals("The number of items in the user's cart is initially zero", 0, itemsInCart); 40 | } 41 | 42 | @Test 43 | public void testLoginFailureWithWrongPassword() throws InterruptedException { 44 | 45 | info("Attempting login as testuser, password: badpassword"); 46 | 47 | assertTrue("Clicking 'login' stays on the same page", true); 48 | 49 | assertTrue("An error message is shown", true); 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/test/java/org/rnorth/visibleassertions/TtyCheckTest.java: -------------------------------------------------------------------------------- 1 | package org.rnorth.visibleassertions; 2 | 3 | import org.fusesource.jansi.internal.CLibrary; 4 | import org.junit.Test; 5 | import org.rnorth.ansi.CapabilityDetection; 6 | 7 | import static org.rnorth.visibleassertions.VisibleAssertions.assertEquals; 8 | import static org.rnorth.visibleassertions.VisibleAssertions.info; 9 | 10 | public class TtyCheckTest { 11 | 12 | @Test 13 | public void checkConsistentTtyDetection() { 14 | info("isTty=" + CapabilityDetection.isTty()); 15 | info("isUnderMaven=" + CapabilityDetection.isUnderMaven()); 16 | info("isUnderIDEA=" + CapabilityDetection.isUnderIDEA()); 17 | 18 | assertEquals("JNA and Jansi detect tty the same", 19 | CapabilityDetection.isTty() ? 1 : 0, 20 | CLibrary.isatty(1)); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/org/rnorth/visibleassertions/VisibleAssertionsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2013 Deloitte Digital and Richard North 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.rnorth.visibleassertions; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.io.ByteArrayOutputStream; 24 | import java.io.PrintStream; 25 | import java.math.BigDecimal; 26 | import java.util.concurrent.Callable; 27 | 28 | import static org.hamcrest.CoreMatchers.equalTo; 29 | import static org.hamcrest.CoreMatchers.is; 30 | import static org.rnorth.visibleassertions.VisibleAssertions.*; 31 | 32 | /** 33 | * @author rnorth 34 | */ 35 | public class VisibleAssertionsTest { 36 | 37 | private ByteArrayOutputStream stdOutBuffer; 38 | private PrintStream originalStdOut; 39 | 40 | @Before 41 | public void setup() { 42 | originalStdOut = System.out; 43 | stdOutBuffer = new ByteArrayOutputStream(); 44 | System.setOut(new PrintStream(stdOutBuffer)); 45 | } 46 | 47 | @After 48 | public void outputForDebugging() { 49 | System.setOut(originalStdOut); 50 | System.out.println("CAPTURED STDOUT:"); 51 | System.out.println(getCapturedStdOut()); 52 | } 53 | 54 | @Test 55 | public void testTrueAssertion() { 56 | assertTrue("it should be true", true); 57 | assert getCapturedStdOut().contains("✔ it should be true"); 58 | } 59 | 60 | @Test 61 | public void testFalseAssertion() { 62 | try { 63 | assertTrue("it should be true", false); 64 | failIfReachedHere(); 65 | } catch (AssertionError expected) { 66 | } 67 | assert getCapturedStdOut().contains("✘ it should be true"); 68 | } 69 | 70 | @Test 71 | public void testNullEqualsAssertion() { 72 | assertEquals("it should be equal", null, null); 73 | assert getCapturedStdOut().contains("✔ it should be equal"); 74 | } 75 | 76 | @Test 77 | public void testEqualsAssertion() { 78 | assertEquals("it should be equal", "A", "A"); 79 | assert getCapturedStdOut().contains("✔ it should be equal"); 80 | } 81 | 82 | @Test 83 | public void testVisiblyEqualsAssertion() { 84 | assertVisiblyEquals("it should be equal", 1, 1L); 85 | assert getCapturedStdOut().contains("✔ it should be equal"); 86 | } 87 | 88 | @Test 89 | public void testOneNullEqualsAssertion() { 90 | try { 91 | assertEquals("it should be equal", null, "A"); 92 | failIfReachedHere(); 93 | } catch (AssertionError expected) { 94 | } 95 | assert getCapturedStdOut().contains("✘ it should be equal"); 96 | assert getCapturedStdOut().contains("'A' does not equal expected null"); 97 | } 98 | 99 | @Test 100 | public void testOneOtherNullEqualsAssertion() { 101 | try { 102 | assertEquals("it should be equal", "A", null); 103 | failIfReachedHere(); 104 | } catch (AssertionError expected) { 105 | } 106 | assert getCapturedStdOut().contains("✘ it should be equal"); 107 | assert getCapturedStdOut().contains("null does not equal expected 'A'"); 108 | } 109 | 110 | @Test 111 | public void testNonEqualsAssertion() { 112 | try { 113 | assertEquals("it should be equal", "B", "A"); 114 | failIfReachedHere(); 115 | } catch (AssertionError expected) { 116 | } 117 | assert getCapturedStdOut().contains("✘ it should be equal"); 118 | assert getCapturedStdOut().contains("'A' does not equal expected 'B'"); 119 | } 120 | 121 | @Test 122 | public void testNonEqualsAssertionForDifferentTypesSameValue() { 123 | try { 124 | assertEquals("it should be equal", 1L, 1); 125 | failIfReachedHere(); 126 | } catch (AssertionError expected) { 127 | } 128 | assert getCapturedStdOut().contains("✘ it should be equal"); 129 | assert getCapturedStdOut().contains("'1' [java.lang.Integer] does not equal expected '1' [java.lang.Long]"); 130 | } 131 | 132 | @Test 133 | public void testNonEqualsAssertionForDifferentTypesSameValueForNonBoxedNonPrimitiveTypes() { 134 | try { 135 | assertEquals("it should be equal", new BigDecimal(1), 1); 136 | failIfReachedHere(); 137 | } catch (AssertionError expected) { 138 | } 139 | assert getCapturedStdOut().contains("✘ it should be equal"); 140 | assert getCapturedStdOut().contains("'1' [java.lang.Integer] does not equal expected '1' [java.math.BigDecimal]"); 141 | } 142 | 143 | @Test 144 | public void testNotVisiblyEqualsAssertion() { 145 | try { 146 | assertVisiblyEquals("it should be equal", new BigDecimal(2), 1); 147 | failIfReachedHere(); 148 | } catch (AssertionError expected) { 149 | } 150 | assert getCapturedStdOut().contains("✘ it should be equal"); 151 | assert getCapturedStdOut().contains("'1' after toString() does not equal expected '2'"); 152 | } 153 | 154 | @Test 155 | public void testNotVisiblyEqualsWithNull() { 156 | try { 157 | assertVisiblyEquals("it should be equal", null, 1); 158 | failIfReachedHere(); 159 | } catch (AssertionError expected) { 160 | } 161 | assert getCapturedStdOut().contains("✘ it should be equal"); 162 | assert getCapturedStdOut().contains("'1' after toString() does not equal expected null"); 163 | } 164 | 165 | @Test 166 | public void testNotEqualsAssertion() { 167 | try { 168 | assertNotEquals("it should not be equal", "A", "A"); 169 | failIfReachedHere(); 170 | } catch (AssertionError expected) { 171 | } 172 | assert getCapturedStdOut().contains("✘ it should not be equal"); 173 | } 174 | 175 | @Test 176 | public void testOneNullNotEqualsAssertion() { 177 | assertNotEquals("it should not be equal", null, "A"); 178 | assert getCapturedStdOut().contains("✔ it should not be equal"); 179 | } 180 | 181 | @Test 182 | public void testOneOtherNullNotEqualsAssertion() { 183 | assertNotEquals("it should not be equal", "A", null); 184 | assert getCapturedStdOut().contains("✔ it should not be equal"); 185 | } 186 | 187 | @Test 188 | public void testNonNotEqualsAssertion() { 189 | assertNotEquals("it should not be equal", "B", "A"); 190 | assert getCapturedStdOut().contains("✔ it should not be equal"); 191 | } 192 | 193 | @Test 194 | public void testRoughlyEqualsAssertion() { 195 | assertRoughlyEquals("it should be equal", 1.9d, 1.9d, 0.1); 196 | assert getCapturedStdOut().contains("✔ it should be equal"); 197 | } 198 | 199 | @Test 200 | public void testRoughlyEqualsAssertionWithRealDifferencePositive() { 201 | assertRoughlyEquals("it should be equal", 1.9d, 1.91d, 0.1); 202 | assert getCapturedStdOut().contains("✔ it should be equal"); 203 | } 204 | 205 | @Test 206 | public void testRoughlyEqualsAssertionWithRealDifferenceNegative() { 207 | assertRoughlyEquals("it should be equal", 1.9d, 1.89d, 0.1); 208 | assert getCapturedStdOut().contains("✔ it should be equal"); 209 | } 210 | 211 | @Test 212 | public void testRoughlyEqualsAssertionWithTooSmallEpsilon() { 213 | try { 214 | assertRoughlyEquals("it should be equal", 1.9d, 1.9d, 0.0); 215 | failIfReachedHere(); 216 | } catch (AssertionError expected) { 217 | } 218 | assert getCapturedStdOut().contains("✘ it should be equal"); 219 | assert getCapturedStdOut().contains("'1.9' differs from expected '1.9' by more than allowed amount (0.0)"); 220 | } 221 | 222 | @Test(expected = RuntimeException.class) 223 | public void testDeliberateFailure() { 224 | try { 225 | int a = 7 / 0; 226 | } catch (Throwable e) { 227 | throw new RuntimeException("A generic exception which wraps the root cause", e); 228 | } 229 | } 230 | 231 | @Test 232 | public void testNullAssertion() { 233 | assertNull("a null thing should be null", null); 234 | assert getCapturedStdOut().contains("✔ a null thing should be null"); 235 | } 236 | 237 | @Test 238 | public void testFailingNullAssertion() { 239 | try { 240 | assertNull("a null thing should be null", "a non-null thing"); 241 | failIfReachedHere(); 242 | } catch (AssertionError expected) { 243 | } 244 | assert getCapturedStdOut().contains("✘ a null thing should be null"); 245 | } 246 | 247 | @Test 248 | public void testNotNullAssertion() { 249 | assertNotNull("a not-null thing should be not-null", "a non-null thing"); 250 | assert getCapturedStdOut().contains("✔ a not-null thing should be not-null"); 251 | } 252 | 253 | @Test 254 | public void testFailingNotNullAssertion() { 255 | try { 256 | assertNotNull("a not-null thing should be not-null", null); 257 | failIfReachedHere(); 258 | } catch (AssertionError expected) { 259 | } 260 | assert getCapturedStdOut().contains("✘ a not-null thing should be not-null"); 261 | } 262 | 263 | @Test 264 | public void testFail() { 265 | try { 266 | fail("a failure reason"); 267 | failIfReachedHere(); 268 | } catch (AssertionError expected) { 269 | } 270 | assert getCapturedStdOut().contains("✘ a failure reason"); 271 | } 272 | 273 | @Test 274 | public void testSameAssertion() { 275 | Object o1 = "A"; 276 | Object o2 = o1; 277 | assertSame("it should be the same", o2, o1); 278 | assert getCapturedStdOut().contains("✔ it should be the same"); 279 | } 280 | 281 | @Test 282 | public void testFailingSameAssertion() { 283 | try { 284 | assertSame("it should be the same", "A", "B"); 285 | failIfReachedHere(); 286 | } catch (AssertionError expected) { 287 | } 288 | assert getCapturedStdOut().contains("✘ it should be the same"); 289 | assert getCapturedStdOut().contains("'B' is not the same (!=) as expected 'A'"); 290 | } 291 | 292 | @Test 293 | public void testFailingSameAssertionForNullExpected() { 294 | try { 295 | assertSame("it should be the same", null, "B"); 296 | failIfReachedHere(); 297 | } catch (AssertionError expected) { 298 | } 299 | assert getCapturedStdOut().contains("✘ it should be the same"); 300 | assert getCapturedStdOut().contains("'B' is not the same (!=) as expected null"); 301 | } 302 | 303 | @Test 304 | public void testFailingSameAssertionForNullActual() { 305 | try { 306 | assertSame("it should be the same", "A", null); 307 | failIfReachedHere(); 308 | } catch (AssertionError expected) { 309 | } 310 | assert getCapturedStdOut().contains("✘ it should be the same"); 311 | assert getCapturedStdOut().contains("null is not the same (!=) as expected 'A'"); 312 | } 313 | 314 | @Test 315 | public void testThatAssertionWithDescription() { 316 | assertThat("the string", "expected value", is(equalTo("expected value"))); 317 | assert getCapturedStdOut().contains("✔ the string is \"expected value\""); 318 | } 319 | 320 | @Test 321 | public void testFailingThatAssertionWithDescription() { 322 | try { 323 | assertThat("the string", "actual value", is(equalTo("expected value"))); 324 | failIfReachedHere(); 325 | } catch (AssertionError expected) { 326 | } 327 | assert getCapturedStdOut().contains("✘ assertion on the string failed"); 328 | assert getCapturedStdOut().contains("asserted that it is \"expected value\" but was \"actual value\""); 329 | } 330 | 331 | @Test 332 | public void testInfoStatement() { 333 | info("This is an informational message"); 334 | assert getCapturedStdOut().contains("ℹ︎ This is an informational message"); 335 | } 336 | 337 | @Test 338 | public void testWarnStatement() { 339 | warn("This is a warning message"); 340 | assert getCapturedStdOut().contains("⚠︎ This is a warning message"); 341 | } 342 | 343 | @Test 344 | public void testContextStatement() { 345 | context("This is the name of a new context"); 346 | context("This is the name of an indented context", 2); 347 | assert getCapturedStdOut().contains("┈┈┈┈ This is the name of a new context ┈┈┈┈"); 348 | assert getCapturedStdOut().contains(" ┈┈┈┈ This is the name of an indented context ┈┈┈┈┈"); 349 | } 350 | 351 | @Test 352 | public void testAssertThrowsWhenNoException() { 353 | try { 354 | assertThrows("It throws a NPE", NullPointerException.class, new Callable() { 355 | public Object call() throws Exception { 356 | // don't throw 357 | return null; 358 | } 359 | }); 360 | failIfReachedHere(); 361 | } catch (AssertionError expected) { 362 | } 363 | 364 | assert getCapturedStdOut().contains("✘ It throws a NPE"); 365 | } 366 | 367 | @Test 368 | public void testAssertThrowsWhenNoExceptionInRunnable() { 369 | try { 370 | assertThrows("It throws a NPE", NullPointerException.class, new Runnable() { 371 | public void run() { 372 | // don't throw 373 | return; 374 | } 375 | }); 376 | failIfReachedHere(); 377 | } catch (AssertionError expected) { 378 | } 379 | 380 | assert getCapturedStdOut().contains("✘ It throws a NPE"); 381 | } 382 | 383 | @Test 384 | public void testAssertThrowsWhenWrongException() { 385 | 386 | try { 387 | assertThrows("It fails with a NPE", NullPointerException.class, new Callable() { 388 | public Object call() throws Exception { 389 | // throw the wrong exception 390 | throw new ArrayIndexOutOfBoundsException(); 391 | } 392 | }); 393 | failIfReachedHere(); 394 | } catch (AssertionError expected) { 395 | } 396 | 397 | assert getCapturedStdOut().contains("✘ It fails with a NPE"); 398 | assert getCapturedStdOut().contains("ArrayIndexOutOfBoundsException was thrown instead of NullPointerException"); 399 | } 400 | 401 | @Test 402 | public void testSilencingOfPasses() { 403 | System.setProperty("visibleassertions.silence.passes", "true"); 404 | 405 | try { 406 | pass("Something passed"); 407 | fail("Something failed"); 408 | } catch (AssertionError expected) { 409 | } 410 | 411 | assert !getCapturedStdOut().contains("Something passed"); 412 | assert getCapturedStdOut().contains("Something failed"); 413 | 414 | System.setProperty("visibleassertions.silence.passes", "false"); 415 | } 416 | 417 | @Test 418 | public void testSilencingOfFailures() { 419 | System.setProperty("visibleassertions.silence.failures", "true"); 420 | 421 | try { 422 | pass("Something passed"); 423 | fail("Something failed"); 424 | } catch (AssertionError expected) { 425 | } 426 | 427 | assert getCapturedStdOut().contains("Something passed"); 428 | assert !getCapturedStdOut().contains("Something failed"); 429 | 430 | System.setProperty("visibleassertions.silence.failures", "false"); 431 | } 432 | 433 | @Test 434 | public void testSilencingOfEverything() { 435 | System.setProperty("visibleassertions.silence", "true"); 436 | 437 | try { 438 | pass("Something passed"); 439 | fail("Something failed"); 440 | } catch (AssertionError expected) { 441 | } 442 | 443 | assert !getCapturedStdOut().contains("Something passed"); 444 | assert !getCapturedStdOut().contains("Something failed"); 445 | 446 | System.setProperty("visibleassertions.silence", "false"); 447 | } 448 | 449 | private void failIfReachedHere() { 450 | throw new IllegalStateException(); 451 | } 452 | 453 | private String getCapturedStdOut() { 454 | return stdOutBuffer.toString(); 455 | } 456 | } 457 | --------------------------------------------------------------------------------