diff --git a/.travis.yml b/.travis.yml index 75350c6..1159aef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,12 @@ addons: - yodl - man dist: trusty -matrix: +language: generic +cache: + apt: true + directories: + - $HOME/.zvm +jobs: include: - env: ZVM_VERSION='4.3.12' - env: ZVM_VERSION='4.3.17' @@ -15,12 +20,26 @@ matrix: - env: ZVM_VERSION='5.1.1' - env: ZVM_VERSION='5.2' - env: ZVM_VERSION='5.3.1' + - stage: deploy + script: skip + deploy: + provider: releases + api_key: + secure: JudjZ9Ou15GKmgOga6qpcxtCKITpq+EnGCUvNAGefuuG/etxSAEdXQfjmC4VBzCAC9Pn1gkABFAASUtZdZ5xxXhxkuU/lTopJxWG2tdxNuvW/wflZNGdnxgWA1PcYptKrLoDRLzUpDtsnnvD75mMvAR8+YjRJk76gWVM02we2JR8WKcD1bchQiqzc7CK2X4kDL6zRayYpwFnFKhA8bTlIEJ36k92liTeW8VNwg+9CAsM2zjWpCKmLXrecNl3e5sO+4ssGU+J4gnWYSC112oEzLJzm3cYsEj8dTuFtVHby1DrLrpW1fPQdF1h1cwjHtQkbKTF5vrNKcCmSGcFxA2YbMu8aMdkEZmwN8JvShFamyyYHi90UTyv8PQ/WYER143zGZinZ2VeSaIlFEvH7R/sbS6t4DjbXV7rHF9Zbg0d3D7p71kNDpbtH1dkX6KXxtqCOOVRwAMhwRJ6c7VCXwj0AZEr6YrqZucPjbLTn9NVtI0WPZPOIL/HhyB6vzB1zunmjQERmcwNcC3gR47mmOPWfh1XaCpIurrZKjF+SfH/mDN6Tr24a9oeae6+subI5LW9G1qP2/GmibDVmlX+F1jE4xxKr6sIrzB/DLdYVtiSnzAmquZnGNunUCOMB6DN4nCajh9X3O/e2DzKImHSHZyYIThytSNyMs885ZBbev6F850= + file: + - zunit + - zunit.zsh-completion + skip_cleanup: true + on: + tags: true + + before_script: +- if [[ $(ls "$HOME/.zvm" | wc -l) -eq 0 ]]; then rm -rf "$HOME/.zvm"; fi - mkdir .bin - curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > .bin/revolver - curl -L https://raw.githubusercontent.com/molovo/color/master/color.zsh > .bin/color - curl -L https://raw.githubusercontent.com/molovo/zvm/master/zvm > .bin/zvm -- curl -L https://raw.githubusercontent.com/molovo/zvm/master/zvm-shell-integration.zsh > zvm-shell-integration.zsh - chmod u+x .bin/{color,revolver,zvm} - export PATH="$HOME/.zvm/bin:$PWD/.bin:$PATH" - zvm use ${ZVM_VERSION} @@ -28,13 +47,3 @@ before_script: script: "./zunit" notifications: email: false -deploy: - provider: releases - api_key: - secure: JudjZ9Ou15GKmgOga6qpcxtCKITpq+EnGCUvNAGefuuG/etxSAEdXQfjmC4VBzCAC9Pn1gkABFAASUtZdZ5xxXhxkuU/lTopJxWG2tdxNuvW/wflZNGdnxgWA1PcYptKrLoDRLzUpDtsnnvD75mMvAR8+YjRJk76gWVM02we2JR8WKcD1bchQiqzc7CK2X4kDL6zRayYpwFnFKhA8bTlIEJ36k92liTeW8VNwg+9CAsM2zjWpCKmLXrecNl3e5sO+4ssGU+J4gnWYSC112oEzLJzm3cYsEj8dTuFtVHby1DrLrpW1fPQdF1h1cwjHtQkbKTF5vrNKcCmSGcFxA2YbMu8aMdkEZmwN8JvShFamyyYHi90UTyv8PQ/WYER143zGZinZ2VeSaIlFEvH7R/sbS6t4DjbXV7rHF9Zbg0d3D7p71kNDpbtH1dkX6KXxtqCOOVRwAMhwRJ6c7VCXwj0AZEr6YrqZucPjbLTn9NVtI0WPZPOIL/HhyB6vzB1zunmjQERmcwNcC3gR47mmOPWfh1XaCpIurrZKjF+SfH/mDN6Tr24a9oeae6+subI5LW9G1qP2/GmibDVmlX+F1jE4xxKr6sIrzB/DLdYVtiSnzAmquZnGNunUCOMB6DN4nCajh9X3O/e2DzKImHSHZyYIThytSNyMs885ZBbev6F850= - file: - - zunit - - zunit.zsh-completion - skip_cleanup: true - on: - tags: true diff --git a/.zunit.yml b/.zunit.yml index 72df6fe..4a56e70 100644 --- a/.zunit.yml +++ b/.zunit.yml @@ -6,3 +6,4 @@ directories: time_limit: 15 fail_fast: true allow_risky: false +verbose: false diff --git a/README.md b/README.md index c70e7d8..fb2df23 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ ZUnit is a powerful unit testing framework for ZSH ## Installation -> **WARNING**: Although the majority of ZUnit's functionality works as expected, it is in the early stages of development, and as such bugs are likely to be present. Please continue with caution, and [report any issues](/~https://github.com/molovo/zunit/issues/new) you may have. +> **WARNING**: Although the majority of ZUnit's functionality works as expected, it is in the early stages of development, and as such bugs are likely to be present. Please continue with caution, and [report any issues](/~https://github.com/zunit-zsh/zunit/issues/new) you may have. ### [Zulu](/~https://github.com/zulu-zsh/zulu) @@ -21,7 +21,7 @@ zulu install zunit ./build.zsh zulu link zunit ``` - + ### Homebrew ```sh @@ -31,14 +31,14 @@ brew install zunit-zsh/zunit/zunit ### Manual ```sh -git clone /~https://github.com/molovo/zunit +git clone /~https://github.com/zunit-zsh/zunit cd ./zunit ./build.zsh chmod u+x ./zunit cp ./zunit /usr/local/bin ``` -> ZUnit requires the utilities [Color](/~https://github.com/molovo/color) and [Revolver](/~https://github.com/molovo/revolver) to be installed, and in your `$PATH`. The zulu or homebrew installation methods will install these dependencies for you. +> ZUnit requires [Revolver](/~https://github.com/molovo/revolver) to be installed, and in your `$PATH`. The zulu or homebrew installation methods will install this dependency for you. ## Writing Tests diff --git a/contributing.md b/contributing.md index 3d1a654..aaef2bd 100644 --- a/contributing.md +++ b/contributing.md @@ -10,7 +10,7 @@ Please note that this project is released with a [Contributor Code of Conduct](c As a user of ZUnit you're the perfect candidate to help us improve our documentation. Typo corrections, error fixes, better explanations, more examples, etc. Open issues for things that could be improved. Anything. Even improvements to this document. -Use the [`docs` label](/~https://github.com/molovo/zunit/labels/docs) to find suggestions for what we'd love to see more documentation on. +Use the [`docs` label](/~https://github.com/zunit-zsh/zunit/labels/docs) to find suggestions for what we'd love to see more documentation on. ### Improve issues @@ -20,30 +20,30 @@ Some issues are created with missing information, not reproducible, or plain inv We're always looking for more opinions on discussions in the issue tracker. It's a good opportunity to influence the future direction of ZUnit. -The [`question` label](/~https://github.com/molovo/zunit/labels/question) is a good place to find ongoing discussions. +The [`question` label](/~https://github.com/zunit-zsh/zunit/labels/question) is a good place to find ongoing discussions. ### Write code You can use issue labels to discover issues you could help out with: -* [`blocked` issues](/~https://github.com/molovo/zunit/labels/blocked) need help getting unstuck -* [`bug` issues](/~https://github.com/molovo/zunit/labels/bug) are known bugs we'd like to fix -* [`enhancement` issues](/~https://github.com/molovo/zunit/labels/enhancement) are features we're open to including -* [`performance` issues](/~https://github.com/molovo/zunit/labels/performance) track ideas on how to improve ZUnit’s performance +* [`blocked` issues](/~https://github.com/zunit-zsh/zunit/labels/blocked) need help getting unstuck +* [`bug` issues](/~https://github.com/zunit-zsh/zunit/labels/bug) are known bugs we'd like to fix +* [`enhancement` issues](/~https://github.com/zunit-zsh/zunit/labels/enhancement) are features we're open to including +* [`performance` issues](/~https://github.com/zunit-zsh/zunit/labels/performance) track ideas on how to improve ZUnit’s performance -The [`help wanted`](/~https://github.com/molovo/zunit/labels/help%20wanted) and [`good for beginner`](/~https://github.com/molovo/zunit/labels/good%20for%20beginner) labels are especially useful. +The [`help wanted`](/~https://github.com/zunit-zsh/zunit/labels/help%20wanted) and [`good for beginner`](/~https://github.com/zunit-zsh/zunit/labels/good%20for%20beginner) labels are especially useful. -You may find an issue is assigned, or has the [`assigned` label](/~https://github.com/molovo/zunit/labels/assigned). Please double-check before starting on this issue because somebody else is likely already working on it. +You may find an issue is assigned, or has the [`assigned` label](/~https://github.com/zunit-zsh/zunit/labels/assigned). Please double-check before starting on this issue because somebody else is likely already working on it. -We'd like to fix [`priority` issues](/~https://github.com/molovo/zunit/labels/priority) first. We'd love to see progress on [`low-priority` issues](/~https://github.com/molovo/zunit/labels/low%20priority) too. [`future` issues](/~https://github.com/molovo/zunit/labels/future) are those that we'd like to get to, but not anytime soon. Please check before working on these since we may not yet want to take on the burden of supporting those features. +We'd like to fix [`priority` issues](/~https://github.com/zunit-zsh/zunit/labels/priority) first. We'd love to see progress on [`low-priority` issues](/~https://github.com/zunit-zsh/zunit/labels/low%20priority) too. [`future` issues](/~https://github.com/zunit-zsh/zunit/labels/future) are those that we'd like to get to, but not anytime soon. Please check before working on these since we may not yet want to take on the burden of supporting those features. ### Hang out in our chat -We have a [chat](https://gitter.im/molovo/zunit). Jump in there and lurk, talk to us, and help others. +We have a [chat](https://gitter.im/zunit-zsh/zunit). Jump in there and lurk, talk to us, and help others. ## Submitting an issue -- The issue tracker is for issues. Use our [chat](https://gitter.im/molovo/zunit) for support. +- The issue tracker is for issues. Use our [chat](https://gitter.im/zunit-zsh/zunit) for support. - Search the issue tracker before opening an issue. - Ensure you're using the latest version of ZUnit. - Use a clear and descriptive title. diff --git a/src/assertions.zsh b/src/assertions.zsh index 7dcd9a7..09f0ace 100644 --- a/src/assertions.zsh +++ b/src/assertions.zsh @@ -2,6 +2,30 @@ # Internal assertion functions # ################################ +### +# Assert one string is a substring if another +### +function _zunit_assert_is_substring_of() { + local value=$1 comparison=$2 + + [[ "$comparison" = *"$value"* ]] && return 0 + + echo "'$value' is not a substring of '$comparison'" + exit 1 +} + +### +# Assert one string is not a substring if another +### +function _zunit_assert_is_not_substring_of() { + local value=$1 comparison=$2 + + [[ "$comparison" != *"$value"* ]] && return 0 + + echo "'$value' is a substring of '$comparison'" + exit 1 +} + ### # Assert that two integers are equal ### @@ -26,6 +50,54 @@ function _zunit_assert_not_equal_to() { exit 1 } +### +# Assert that an integer is positive +### +function _zunit_assert_is_positive() { + local value=$1 comparison=$2 + + [[ $value -gt 0 ]] && return 0 + + echo "'$value' is not positive" + exit 1 +} + +### +# Assert that an integer is negative +### +function _zunit_assert_is_negative() { + local value=$1 comparison=$2 + + [[ $value -lt 0 ]] && return 0 + + echo "'$value' is not negative" + exit 1 +} + +### +# Assert that an integer is greater than the comparison +### +function _zunit_assert_is_greater_than() { + local value=$1 comparison=$2 + + [[ $value -gt $comparison ]] && return 0 + + echo "'$value' is not greater than '$comparison'" + exit 1 +} + +### +# Assert that an integer is less than the comparison +### +function _zunit_assert_is_less_than() { + local value=$1 comparison=$2 + + [[ $value -lt $comparison ]] && return 0 + + echo "'$value' is not less than '$comparison'" + exit 1 +} + ### # Assert that two string are the same ### diff --git a/src/commands/init.zsh b/src/commands/init.zsh index 5f8e68b..0cfd6f7 100644 --- a/src/commands/init.zsh +++ b/src/commands/init.zsh @@ -71,7 +71,7 @@ allow_risky: false" zsh install: - mkdir .bin - - curl -L /~https://github.com/molovo/zunit/releases/download/v$(_zunit_version)/zunit > .bin/zunit + - curl -L /~https://github.com/zunit-zsh/zunit/releases/download/v$(_zunit_version)/zunit > .bin/zunit - curl -L https://raw.githubusercontent.com/molovo/revolver/master/revolver > .bin/revolver - curl -L https://raw.githubusercontent.com/molovo/color/master/color.zsh > .bin/color before_script: diff --git a/src/commands/run.zsh b/src/commands/run.zsh index d5e8590..9207233 100644 --- a/src/commands/run.zsh +++ b/src/commands/run.zsh @@ -14,6 +14,7 @@ function _zunit_run_usage() { echo " -v, --version Output version information and exit" echo " -f, --fail-fast Stop the test runner immediately after the first failure" echo " -t, --tap Output results in a TAP compatible format" + echo " --verbose Prints full output from each test" echo " --output-text Print results to a text log, in TAP compatible format" echo " --output-html Print results to a HTML page" echo " --allow-risky Supress warnings generated for risky tests" @@ -24,18 +25,18 @@ function _zunit_run_usage() { # Format a ms timestamp in a human-readable format ### function _zunit_human_time() { - local ms=$1 local tmp=$(( $1 / 1000 )) local days=$(( tmp / 60 / 60 / 24 )) local hours=$(( tmp / 60 / 60 % 24 )) local minutes=$(( tmp / 60 % 60 )) local seconds=$(( tmp % 60 )) + local ms=$(( $1 % 1000 )) (( $days > 0 )) && print -n "${days}d " (( $hours > 0 )) && print -n "${hours}h " (( $minutes > 0 )) && print -n "${minutes}m " (( $seconds > 5 )) && print -n "${seconds}s " - (( $seconds < 30 )) && (( $seconds > 5 )) && print -n "$(( ms - $((seconds*1000)) ))ms" - (( $tmp <= 5 )) && print -n "${1}ms" + (( $seconds < 30 )) && (( $seconds > 5 )) && print -n "${ms}ms" + (( $seconds <= 5 )) && print -n "${1}ms" } ### @@ -166,6 +167,7 @@ function _zunit_execute_test() { # The kill time has been reached, kill the child process, # and exit the wrapper function kill -9 $pid >/dev/null 2>&1 + echo "Test took too long to run. Terminated after $time_limit seconds" exit 78 fi done @@ -190,14 +192,20 @@ function _zunit_execute_test() { return elif [[ $state -eq 78 ]]; then - _zunit_error "Test took too long to run. Terminated after $time_limit seconds" $output + _zunit_error $output return elif [[ -z $allow_risky && $state -eq 248 ]]; then + # If --verbose is specified, print test output to screen + [[ -n $verbose && -n $output ]] && echo $output + _zunit_warn 'No assertions were run, test is risky' return elif [[ -n $allow_risky && $state -eq 248 ]] || [[ $state -eq 0 ]]; then + # If --verbose is specified, print test output to screen + [[ -n $verbose && -n $output ]] && echo $output + _zunit_success return @@ -426,7 +434,7 @@ function _zunit_parse_argument() { ### function _zunit_run() { local -a arguments testfiles - local fail_fast tap allow_risky + local fail_fast tap allow_risky verbose local output_text logfile_text output_html logfile_html # Load the datetime module, and record the start time @@ -438,6 +446,7 @@ function _zunit_run() { v=version -version=version \ f=fail_fast -fail-fast=fail_fast \ t=tap -tap=tap \ + -verbose=verbose \ -output-text=output_text \ -output-html=output_html \ -allow-risky=allow_risky \ @@ -520,6 +529,11 @@ function _zunit_run() { allow_risky=1 fi + # Check if verbose is specified in the config or as an option + if [[ -z $verbose ]] && [[ "$zunit_config_verbose" = "true" ]]; then + verbose=1 + fi + # Check if time_limit is specified in the config or as an option if [[ -n $time_limit ]]; then shift time_limit diff --git a/src/helpers.zsh b/src/helpers.zsh index e044127..b634566 100644 --- a/src/helpers.zsh +++ b/src/helpers.zsh @@ -2,6 +2,35 @@ # Helpers for use within tests # ################################ +### +# Colorise and style a string +### +function color() { + local color=$1 style=$2 b=0 + + shift + + case $style in + bold|b) b=1; shift ;; + italic|i) b=2; shift ;; + underline|u) b=4; shift ;; + inverse|in) b=7; shift ;; + strikethrough|s) b=9; shift ;; + esac + + case $color in + black|b) echo "\033[${b};30m${@}\033[0;m" ;; + red|r) echo "\033[${b};31m${@}\033[0;m" ;; + green|g) echo "\033[${b};32m${@}\033[0;m" ;; + yellow|y) echo "\033[${b};33m${@}\033[0;m" ;; + blue|bl) echo "\033[${b};34m${@}\033[0;m" ;; + magenta|m) echo "\033[${b};35m${@}\033[0;m" ;; + cyan|c) echo "\033[${b};36m${@}\033[0;m" ;; + white|w) echo "\033[${b};37m${@}\033[0;m" ;; + *) echo "\033[${b};38;5;$(( ${color} ))m${@}\033[0;m" ;; + esac +} + ### # Find a file, and load it into the environment ### @@ -75,6 +104,11 @@ function run() { # Restore $IFS IFS=$oldIFS + # Print the command output if --verbose is specified + if [[ -n $verbose && -n $output ]]; then + echo $output + fi + # Restore the exit on error state setopt ERR_EXIT } @@ -124,6 +158,37 @@ function assert() { IFS=$oldIFS } +### +# Mark the current test as passed +### +function pass() { + # Exit code 0 will end the test, and mark is as passed. The reason for + # skipping is echoed to stdout first, so that it can be picked up by the + # error handler + exit 0 +} + +### +# Mark the current test as failed +### +function fail() { + # Any non-zero exit code without special meaning will mark the test as failed. + # The failure message is echoed to stdout first, so that it can be picked up + # by the error handler + echo "$@" + exit 1 +} + +### +# Mark the current test as skipped +### +function error() { + # Exit code 78 will end the test, and report an error. The error message + # is echoed to stdout first, so that it can be picked up by the error handler + echo "$@" + exit 78 +} + ### # Mark the current test as skipped ### diff --git a/src/reports/html.zsh b/src/reports/html.zsh index 3dd4c79..8185019 100644 --- a/src/reports/html.zsh +++ b/src/reports/html.zsh @@ -6,7 +6,7 @@ # The head of the HTML document used to display results ### function _zunit_html_header() { - echo ' ZUnit Test Results