diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 01a1c95..5c74984 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,15 @@ You can contribute by: If you're using visual studio code, [recommended extensions](./.vscode/extensions.json) would install useful linters and extensions. +## Tests + +**Automated tests**: + +- Test all: `bash ./tests/run.sh`. +- Defined as `.test.sh` files in [`./tests`](./tests/). + +- **Manual tests**: See documentation in [docker-entrypoint](./tests/docker-entrypoint) + ## Style guide - Do not introduce any TODO comments, fix them or do not introduce the change. diff --git a/README.md b/README.md index 4ee2955..f7e1f37 100644 --- a/README.md +++ b/README.md @@ -152,15 +152,6 @@ You can also use following scripts individually (check script files for usage, p [↑](#bump-everywhere) -## Tests - -- **Automated tests** - - Test all: `bash ./tests/run.sh` - - Defined as `.test.sh` files in [`./tests`](./tests/) -- **Manual tests**: See documentation in [docker-entrypoint](./tests/docker-entrypoint) - -[↑](#bump-everywhere) - ## GitOps CI/CD is fully automated for this repo using different GIT events and GitHub actions. diff --git a/scripts/bump-and-tag-version.sh b/scripts/bump-and-tag-version.sh index 64a6931..6a88ed3 100644 --- a/scripts/bump-and-tag-version.sh +++ b/scripts/bump-and-tag-version.sh @@ -21,13 +21,13 @@ readonly DEFAULT_VERSION="0.1.0" source "$SCRIPTS_DIRECTORY/shared/utilities.sh" tag_and_push() { - local -r tag="$1" - echo "Creating tag: \"$tag\"" - git tag "$tag" \ - || { echo "Could not tag: \"$tag\"" ; exit 1; } - git push -u origin master "$tag" \ - || { echo "Could not push the tag: \"$tag\""; exit 1; } - echo "Tag created and pushed: \"$tag\"" + local -r tag="$1" + echo "Creating tag: \"$tag\"" + git tag "$tag" \ + || { echo "Could not tag: \"$tag\"" ; exit 1; } + git push -u origin "$tag" \ + || { echo "Could not push the tag: \"$tag\""; exit 1; } + echo "Tag created and pushed: \"$tag\"" } increase_patch_version() { diff --git a/scripts/bump-everywhere.sh b/scripts/bump-everywhere.sh index a8d7ba2..9b3a961 100644 --- a/scripts/bump-everywhere.sh +++ b/scripts/bump-everywhere.sh @@ -133,7 +133,7 @@ commit_and_push() { local -r printable_commit_message=${commit_message/$VERSION_PLACEHOLDER/$latest_version_tag} git commit -m "$printable_commit_message" \ || { echo "Could not commit wit the message: $printable_commit_message"; exit 1; } - git push -u origin master \ + git push -u origin \ || { echo "Could not git push changes"; exit 1; } fi } diff --git a/tests/bump-and-tag-version.test.sh b/tests/bump-and-tag-version.test.sh index 6ec5e48..42ead5c 100755 --- a/tests/bump-and-tag-version.test.sh +++ b/tests/bump-and-tag-version.test.sh @@ -6,56 +6,120 @@ readonly SELF_DIRECTORY=$(dirname "$0") source "$SELF_DIRECTORY/test-utilities.sh" main() { - run_test test_increase_patch_version + test_utilities::run_tests \ + test_increase_patch_version \ + test_sets_initial_version \ + test_tags_within_any_branch +} + +test_tags_within_any_branch() { + # Arrange + local -r branch_name='uncommon/branch-name' + initialize_empty_repository "$branch_name" + git commit --message "Tagged commit" --allow-empty || { echo '😢 Cannot do first commit'; return 1; } + local -r expected_commit_sha_to_tag="$(git rev-parse HEAD)" + + # Act + if ! run_sut; then + return 1 + fi + + # Assert + local -r tag="$(git describe --tags --abbrev=0)" + local -r actual_commit_sha=$(git rev-parse "$tag") + if ! test_utilities::assert_equals "$expected_commit_sha_to_tag" "$actual_commit_sha" 'Unexpected commit.'; then + ((total_errors++)) + fi +} + +test_sets_initial_version() { + # Arrange + local -r expected_tag='0.1.0' + + initialize_empty_repository 'master' + git commit --message "Tagged commit" --allow-empty || { echo '😢 Cannot do first commit'; return 1; } + local -r expected_commit_sha_to_tag="$(git rev-parse HEAD)" + + # Act + if ! run_sut; then + return 1 + fi + + # Assert + assert_expected_latest_tag "$expected_tag" "$expected_commit_sha_to_tag" + return "$?" } test_increase_patch_version() { - local -i result=0 - - expect_version '1.5.3' '1.5.4' - ((result+=$?)) - - expect_version '0.0.0' '0.0.1' - ((result+=$?)) - - expect_version '1.22.333' '1.22.334' - ((result+=$?)) - - expect_version '31.31.31' '31.31.32' - ((result+=$?)) - - return "$result" -} - -expect_version() { - # Prepare - local -r given="$1" - local -r expected="$2" - local actual - - rm -rf .git - git init -b master --quiet || { echo '😢 Could not initialize git repository'; return 1; } - git remote add origin "$(pwd)" || { echo "😢 Could not add fake origin: $(pwd)"; return 1; } - git config --local user.email "test@privacy.sexy" || { echo '😢 Could not set user e-mail'; return 1; } - git config --local user.name "Test User" || { echo '😢 Could not set user name'; return 1; } - git commit --message "Tagged commit" --allow-empty || { echo '😢 Cannot do first commit'; return 1; } - git tag "$given" || { echo "😢 Cannot tag $given"; return 1; } - git commit --message "Empty commit" --allow-empty || { echo '😢 Cannot do second commit'; return 1; } - - # Act - local -r sut=$(get_absolute_sut_path bump-and-tag-version.sh) || { echo '😢 Could not locate sut'; return 1; } - echo "Sut: $sut" - bash "$sut" - - # Assert - local -r actual="$(git describe --tags --abbrev=0)" - if [[ "$actual" == "$expected" ]]; then - echo -e "Success: $given returned $actual as expected." - return 0 - else - echo "Fail: Given $given, $expected (expected) != $actual (actual)." - return 1 - fi + local -i result=0 + + test_version_increase '1.5.3' '1.5.4' + ((result+=$?)) + + test_version_increase '0.0.0' '0.0.1' + ((result+=$?)) + + test_version_increase '1.22.333' '1.22.334' + ((result+=$?)) + + test_version_increase '31.31.31' '31.31.32' + ((result+=$?)) + + return "$result" +} + +test_version_increase() { + # Arrange + local -r given="$1" + local -r expected_tag="$2" + + initialize_empty_repository 'master' + git commit --message "Tagged commit" --allow-empty || { echo '😢 Cannot do first commit'; return 1; } + git tag "$given" || { echo "😢 Cannot tag $given"; return 1; } + git commit --message "Empty commit" --allow-empty || { echo '😢 Cannot do second commit'; return 1; } + local -r expected_commit_sha_to_tag="$(git rev-parse HEAD)" + + # Act + if ! run_sut; then + return 1 + fi + + # Assert + assert_expected_latest_tag "$expected_tag" "$expected_commit_sha_to_tag" + return "$?" +} + +initialize_empty_repository() { + local -r branch_name="$1" + rm -rf .git + git init -b "$branch_name" --quiet || { echo '😢 Could not initialize git repository'; return 1; } + git remote add origin "$(pwd)" || { echo "😢 Could not add fake origin: $(pwd)"; return 1; } + git config --local user.email "test@privacy.sexy" || { echo '😢 Could not set user e-mail'; return 1; } + git config --local user.name "Test User" || { echo '😢 Could not set user name'; return 1; } +} + +run_sut() { + test_utilities::run_script 'bump-and-tag-version.sh' + return "$?" +} + +assert_expected_latest_tag() { + local -r expected_tag="$1" + local -r expected_commit_sha_to_tag="$2" + + local -i total_errors=0 + + local -r actual_tag="$(git describe --tags --abbrev=0)" + if ! test_utilities::assert_equals "$expected_tag" "$actual_tag" 'Unexpected tag.'; then + ((total_errors++)) + fi + + local -r actual_commit_sha=$(git rev-parse "$actual_tag") + if ! test_utilities::assert_equals "$expected_commit_sha_to_tag" "$actual_commit_sha" 'Unexpected commit.'; then + ((total_errors++)) + fi + + return "$total_errors" } main diff --git a/tests/bump-npm-version.test.sh b/tests/bump-npm-version.test.sh index 9b727b9..413d276 100644 --- a/tests/bump-npm-version.test.sh +++ b/tests/bump-npm-version.test.sh @@ -5,76 +5,68 @@ readonly SELF_DIRECTORY=$(dirname "$0") # shellcheck source=test-utilities.sh source "$SELF_DIRECTORY/test-utilities.sh" -test() { - # arrange - local sut - local -r initial_version='0.1.0' - local -r new_version='0.2.10' - local -r expected_package_content=$(print_package_json "$new_version") - local -r expected_package_lock_content=$(print_package_lock_json "$new_version") - sut=$(get_absolute_sut_path "bump-npm-version.sh") || { echo '😢 Could not locate sut'; return 1; } - echo "Sut: $sut" - setup_git_env "$initial_version" "$new_version" || { echo "Could not setup the test environment"; return 1; } +main() { + test_utilities::run_tests test_json_version_bump +} - # act - echo "Setup repository" - if ! bash "$sut"; then - echo "Unexpected exit code: $?"; - return 1; - fi +test_json_version_bump() { + # Arrange + local -r initial_version='0.1.0' + local -r new_version='0.2.10' + local -r expected_package_content=$(print_package_json "$new_version") + local -r expected_package_lock_content=$(print_package_lock_json "$new_version") + setup_git_env "$initial_version" "$new_version" || { echo "Could not setup the test environment"; return 1; } - # assert - local -r current_dir="$(pwd)" - echo "$current_dir" - local -r package_content="$(cat 'package.json')" - local -r package_lock_content="$(cat 'package-lock.json')" - local -i status=0 - are_equal_json 'package.json' "$package_content" "$expected_package_content" || status=1 - are_equal_json 'package-lock.json' "$package_lock_content" "$expected_package_lock_content" || status=1 - return $status -} + # Act + echo "Setup repository" + if ! test_utilities::run_script 'bump-npm-version.sh'; then + echo 'Running sut failed.' + return 1; + fi -setup_git_env() { - local -r initial_version="$1" - local -r new_version="$2" - echo "Setting up git environment, initial version: \"$initial_version\", new version: \"$new_version\"" - git init -b master --quiet || { echo '😢 Could not initialize git repository'; return 1; } - git config --local user.email "test@privacy.sexy" || { echo '😢 Could not set user e-mail'; return 1; } - git config --local user.name "Test User" || { echo '😢 Could not set user name'; return 1; } - print_package_json "$initial_version" > "package.json" - print_package_lock_json "$initial_version" > "package-lock.json" - git add . || { echo '😢 Could not add git changes'; return 1; } - git commit -m "inital commit" --quiet || { echo '😢 Could not do initial commit'; return 1; } - git tag "$initial_version" || { echo '😢 Could tag first version'; return 1; } - git commit -m "next commit" --allow-empty --quiet || { echo '😢 Could not do next commit'; return 1; } - git tag "$new_version" || { echo '😢 Could tag next version'; return 1; } - return 0 + # Assert + local -r current_dir="$(pwd)" + echo "$current_dir" + local -r package_content="$(cat 'package.json')" + local -r package_lock_content="$(cat 'package-lock.json')" + local -i status=0 + assert_equals_json 'package.json' "$package_content" "$expected_package_content" || status=1 + assert_equals_json 'package-lock.json' "$package_lock_content" "$expected_package_lock_content" || status=1 + return $status } -main() { - run_test test +setup_git_env() { + local -r initial_version="$1" + local -r new_version="$2" + echo "Setting up git environment, initial version: \"$initial_version\", new version: \"$new_version\"" + git init -b master --quiet || { echo '😢 Could not initialize git repository'; return 1; } + git config --local user.email "test@privacy.sexy" || { echo '😢 Could not set user e-mail'; return 1; } + git config --local user.name "Test User" || { echo '😢 Could not set user name'; return 1; } + print_package_json "$initial_version" > "package.json" + print_package_lock_json "$initial_version" > "package-lock.json" + git add . || { echo '😢 Could not add git changes'; return 1; } + git commit -m "inital commit" --quiet || { echo '😢 Could not do initial commit'; return 1; } + git tag "$initial_version" || { echo '😢 Could tag first version'; return 1; } + git commit -m "next commit" --allow-empty --quiet || { echo '😢 Could not do next commit'; return 1; } + git tag "$new_version" || { echo '😢 Could tag next version'; return 1; } + return 0 } print_package_json() { - local -r version="$1" - echo "{ \"version\": \"$version\" }" + local -r version="$1" + echo "{ \"version\": \"$version\" }" } print_package_lock_json() { - local -r version="$1" - echo "{ \"version\": \"$version\", \"dependencies\": { \"ez-consent\": { \"version\": \"1.2.1\" } } }" + local -r version="$1" + echo "{ \"version\": \"$version\", \"dependencies\": { \"ez-consent\": { \"version\": \"1.2.1\" } } }" } -are_equal_json() { - local -r name="$1" - local -r actual="$(echo "$2" | jq -cS)" - local -r expected="$(echo "$3" | jq -cS)" - if [ "$actual" == "$expected" ]; then - return 0 - else - echo "Unexpected $name. Actual: \"$actual\". Expected: \"$expected\"" - return 1 - fi +assert_equals_json() { + local -r name="$1" + local -r actual="$(echo "$2" | jq -cS)" + local -r expected="$(echo "$3" | jq -cS)" + test_utilities::assert_equals "$expected" "$actual" "Unexpected $name." } main diff --git a/tests/run.sh b/tests/run.sh old mode 100644 new mode 100755 index b31c77e..daf7db8 --- a/tests/run.sh +++ b/tests/run.sh @@ -1,7 +1,9 @@ #!/usr/bin/env bash +# Import dependencies readonly SELF_DIRECTORY=$(dirname "$0") - +# shellcheck source=test-utilities.sh +source "$SELF_DIRECTORY/test-utilities.sh" main() { local succeeded_tests=() @@ -21,8 +23,7 @@ main() { failed_tests+=("$file") echo $'\t'"🔴 Failed." fi - # shellcheck disable=SC2001 - echo "$output" | sed 's/^/\t/' # Tab indent output + echo "$output" | test_utilities::tab_indent_to_right done # Report @@ -47,4 +48,4 @@ main() { } -main \ No newline at end of file +main diff --git a/tests/test-utilities.sh b/tests/test-utilities.sh index a2b9ce1..e58745f 100644 --- a/tests/test-utilities.sh +++ b/tests/test-utilities.sh @@ -3,41 +3,98 @@ # Globals readonly ABSOLUTE_SELF_DIRECTORY=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +test_utilities::assert_equals() { + local -r expected="$1" + local -r actual="$2" + local -r error_message="$3" + if [[ "$actual" == "$expected" ]]; then + echo "[SUCCESS] expected: $expected == actual: $actual" + return 0 + else + echo "[FAIL] $error_message (expected: $expected !== actual: $actual)" + return 1 + fi +} -get_absolute_sut_path() -{ - local -r path_from_scripts="$1" - local -r script_dir="$ABSOLUTE_SELF_DIRECTORY/../scripts" - local normalized - if ! normalized=$(cd "${script_dir}" || return 1;pwd; return 0); then - echo "Dir does not exist: ${script_dir}" - return 1 - fi - local -r script_path="$normalized/$path_from_scripts" - echo "$script_path" +test_utilities::run_script() { + local script_path="$1" + + local sut_path + + if ! sut_path=$(__get_absolute_sut_path "$script_path"); then + echo '😢 Could not locate sut' + return 1 + fi + + echo "Sut (\"$sut_path\"):" + + bash "$sut_path" | test_utilities::tab_indent_to_right + local -r exit_code="${PIPESTATUS[0]}" + + if [[ "$exit_code" -ne 0 ]]; then + echo "$script_path ended with unexpected exit code: $exit_code." + fi + + return "$exit_code" } # Takes test function delegate as argument and then: # 1. Creates a temporary directory, navigates to it # 2. Runs the test # 3. Cleans temporary directory, returns the test result -run_test() { - # Beging - local -r temp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'bumpeverywheretmpdir') - echo "Test dir: \"$temp_dir\"" - if ! cd "$temp_dir"; then - echo "😢 Could not navigate to $temp_dir" - return 1 +test_utilities::run_tests() { + local -ra test_function_references=("$@") + local -i total_fails=0 + + for test_function_reference in "${test_function_references[@]}"; do + if ! __run_test "$test_function_reference"; then + ((total_fails++)) fi + done + + if [[ "$total_fails" -eq 0 ]]; then + echo "🟢 All tests passed (total run: ${#test_function_references[@]})." + else + echo "🔴 Some tests failed (total failed/run: $total_fails/${#test_function_references[@]})." + fi - # Test - $1 - local -i -r test_exit_code="$?" - echo "Test exit code: $test_exit_code" + return "$total_fails" +} - # Clean - rm -rf "$temp_dir" - echo "Cleaned \"$temp_dir\"" - exit "$test_exit_code" +test_utilities::tab_indent_to_right() { + local -r input=$(/dev/null || mktemp -d -t 'bumpeverywheretmpdir') + echo "Test dir: \"$temp_dir\"" + if ! cd "$temp_dir"; then + echo "😢 Could not navigate to $temp_dir" + return 1 + fi + + # Test + $1 + local -i -r test_exit_code="$?" + echo "Test exit code: $test_exit_code" + + # Clean + rm -rf "$temp_dir" + echo "Cleaned \"$temp_dir\"" + return "$test_exit_code" +} + +__get_absolute_sut_path() +{ + local -r path_from_scripts="$1" + local -r script_dir="$ABSOLUTE_SELF_DIRECTORY/../scripts" + local normalized + if ! normalized=$(cd "${script_dir}" || return 1;pwd; return 0); then + echo "Dir does not exist: ${script_dir}" + return 1 + fi + local -r script_path="$normalized/$path_from_scripts" + echo "$script_path" +}