From e6dae9379c514492f1cc5c5d6adddbafa90dcbdd Mon Sep 17 00:00:00 2001 From: Michael Billington Date: Sat, 3 Jun 2017 21:57:37 +1000 Subject: [PATCH] add very basic tests --- .travis.yml | 1 + mdcheckr | 44 +++++++++++++++++++++++++++--- tests/00_rel_link_bad.md | 6 +++++ tests/00_rel_link_good.md | 6 +++++ tests/01_abs_link_bad.md | 6 +++++ tests/01_abs_link_good.md | 6 +++++ tests/test.sh | 57 +++++++++++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 4 deletions(-) create mode 100644 tests/00_rel_link_bad.md create mode 100644 tests/00_rel_link_good.md create mode 100644 tests/01_abs_link_bad.md create mode 100644 tests/01_abs_link_good.md create mode 100755 tests/test.sh diff --git a/.travis.yml b/.travis.yml index e6ce8c8..8d40768 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ - script: - bash -n mdcheckr + - (cd tests && ./test.sh) - ./mdcheckr README.md diff --git a/mdcheckr b/mdcheckr index 23dca36..33bc16d 100755 --- a/mdcheckr +++ b/mdcheckr @@ -1,9 +1,34 @@ #!/bin/bash set -e +# mdcheckr: practical CI testing for markdown files +# Copyright (c) 2017 Michael Billington < michael.billingotn@gmail.com > +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. -# Extract URLs from Markdown file via Pandoc function extract_links() { - pandoc -f markdown_github "$fn" | (xmllint --nowarning --html --xpath '*//a/@href' - 2> /dev/null || true) | sed 's/ href="\([^"]*\)"/\1\n/g' + # Extract URLs from Markdown file: + # - Render via Pandoc + # - Extract URI via href="" attribute + # - Format as one URI per line + pandoc -f markdown_github "$1" | \ + (xmllint --nowarning --html --xpath '*//a/@href' - 2> /dev/null || true) | \ + sed 's/ href="\([^"]*\)"/\1\n/g' } function green() { @@ -26,7 +51,7 @@ for i in $@; do # Jump into same dir as file cd `dirname "$i"` echo "Checking $i .." - extract_links "$fn" | while read -r line; do + while read -r line; do # Notify of check echo -n "- $line "; fail=0 @@ -41,9 +66,20 @@ for i in $@; do if [ "$fail" == 1 ]; then red "FAIL" explain "$i" "$REASON" + failures=$((failures+1)) else green "OK" fi - done; + done < <(extract_links "$fn") done + +# Return to initial directory cd $DIR + +# Log number of failures +if [ "$failures" -gt 0 ]; then + echo "Done, with $failures warning(s)." +fi + +# Use number of failures as exit code +exit $failures diff --git a/tests/00_rel_link_bad.md b/tests/00_rel_link_bad.md new file mode 100644 index 0000000..131c955 --- /dev/null +++ b/tests/00_rel_link_bad.md @@ -0,0 +1,6 @@ +# Good link + +This is an example of a URL to a local file which does not exist: + +[not_a_real_file.md](not_a_real_file.md) + diff --git a/tests/00_rel_link_good.md b/tests/00_rel_link_good.md new file mode 100644 index 0000000..3d89b26 --- /dev/null +++ b/tests/00_rel_link_good.md @@ -0,0 +1,6 @@ +# Good link + +This is an example of a URL to a local file which exists: + +[00_rel_link_good.md](00_rel_link_good.md) + diff --git a/tests/01_abs_link_bad.md b/tests/01_abs_link_bad.md new file mode 100644 index 0000000..75be05f --- /dev/null +++ b/tests/01_abs_link_bad.md @@ -0,0 +1,6 @@ +# Good link + +This is an example of a URL to a remote file which does not exist: + +[http://example.com/not_a_real_file](http://example.com/not_a_real_file) + diff --git a/tests/01_abs_link_good.md b/tests/01_abs_link_good.md new file mode 100644 index 0000000..12afc18 --- /dev/null +++ b/tests/01_abs_link_good.md @@ -0,0 +1,6 @@ +# Good link + +This is an example of a URL to a remote file which does exist: + +[http://example.com/](http://example.com/) + diff --git a/tests/test.sh b/tests/test.sh new file mode 100755 index 0000000..4d75c09 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,57 @@ +#!/bin/bash +# test.sh: Execute test cases over mdcheckr script. +# The test cases themselves are simply markdown files. Those ending in "good" +# are expected to validate, while "bad" examples are expected to be picked up. +set -e + +# Functions to wrap test output +function green() { + echo -e "\033[32m[ \e[1m$1\e[21m ]\e[0m" +} + +function red() { + echo -e "\033[31m[ \e[1m$1\e[21m ]\e[0m" +} + +function explain { + >&2 echo -e Warning:$1:$2 +} + +# Executable path +mdcheckr="../mdcheckr" + +# Start at 0 failures +failures=0 + +# Confirm that good examples pass +find . -name '*_good.md' -print0 | tr '\0' '\n' | while read -r line; do + echo -n "Expecting '$line' to pass without errors " + if ! $mdcheckr "$line" > /dev/null 2> /dev/null; then + red "FAIL" + failures=$((failures+1)) + else + green "OK" + fi +done + +# Confirm that bad examples fail +while read -r line; do + echo -n "Expecting '$line' to raise errors " + if $mdcheckr "$line" > /dev/null 2> $line.err.actual; then + red "FAIL" + failures=$((failures+1)) + explain "$line" "Expected to see errors from this file" + else + # TODO compare actual and expected failure output here + green "OK" + fi + rm -f $line.err.actual +done < <(find . -name '*_bad.md' -print0 | tr '\0' '\n') + +# Log number of failures +if [ "$failures" -gt 0 ]; then + echo "Done, with $failures failed test(s)." +fi + +# Use number of failures as exit code +exit $failures