Skip to content

Commit

Permalink
Fix patch number increase #13
Browse files Browse the repository at this point in the history
This was caused by unintended escape where word splitting was intended.

Rewrite the logic with more robust implementation with clear word
splitting using `read`.

Add tests for the bug, automate test run and reuse some of test logic in
tests. Finally, introduce introduce `tests/run.sh` to automatically
discover and run tests.
  • Loading branch information
undergroundwires committed Dec 21, 2021
1 parent 51e11bf commit 1bdaeef
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 47 deletions.
16 changes: 8 additions & 8 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ on: [ push ]

jobs:

build-docker:
name: Build docker
run-tests:
name: Run automated tests
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Build docker
run: docker build . --tag bump-everywhere
name: Run all tests
run: bash ./tests/run.sh

run-tests:
name: Run tests
build-docker:
name: Ensure ability to build docker
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: bump-npm-version
run: bash ./tests/bump-npm-version.test.sh
name: Build docker
run: docker build . --tag bump-everywhere
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,9 @@ You can also use following scripts individually (check script files for usage, p

## Tests

- **Automated tests**: Run `.test.sh` files in [`./tests`](./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)
Expand Down
11 changes: 5 additions & 6 deletions scripts/bump-and-tag-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,11 @@ tag_and_push() {

increase_patch_version() {
local -r version="$1"
local -r version_bits=("${version//./ }") # Replace . with space so can split into an array
local -r major=${version_bits[0]}
local -r minor=${version_bits[1]}
local patch=${version_bits[2]}
patch=$((patch+1))
printf "%s.%s.%s" "$major" "$minor" "$patch"
local IFS='.' # Use "local" so we do not potentially break other scripts
read -ra version_parts <<< "$version" # Split to (-a:) array without (-r:) allowing backslashes to escape
((version_parts[2]++)) # Increase patch version (after second dot; major.minor.<patch>)
new_version="${version_parts[*]}" # Join parts back using same IFS
echo "$new_version"
}

is_latest_commit_tagged() {
Expand Down
61 changes: 61 additions & 0 deletions tests/bump-and-tag-version.test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash

# Import dependencies
readonly SELF_DIRECTORY=$(dirname "$0")
# shellcheck source=tests/test-utilities.sh
source "$SELF_DIRECTORY/test-utilities.sh"

main() {
run_test test_increase_patch_version
}

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 "[email protected]" || { 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
}

main
40 changes: 8 additions & 32 deletions tests/bump-npm-version.test.sh
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
#!/usr/bin/env bash

# Import dependencies
readonly SELF_DIRECTORY=$(dirname "$0")
# shellcheck source=tests/test-utilities.sh
source "$SELF_DIRECTORY/test-utilities.sh"

test() {
# arrange
local -r git_dir="$1"
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) || { echo '😢 Could not locate sut'; return 1; }
sut=$(get_absolute_sut_path "bump-npm-version.sh") || { echo '😢 Could not locate sut'; return 1; }
echo "Sut: $sut"
cd "$git_dir" || { echo "Cannot navigate to temp dir: \"$git_dir\""; return 1; }
setup_git_env "$initial_version" "$new_version" || { echo "Could not setup the test environment"; return 1; }

# act
echo "Setup repository in \"$git_dir\""
echo "Setup repository"
if ! bash "$sut"; then
echo "Unexpected exit code: $?";
return 1;
Expand Down Expand Up @@ -49,34 +52,7 @@ setup_git_env() {
}

main() {
# begin
local -r temp_dir=$(mktemp -d 2>/dev/null || mktemp -d -t 'bumpeverywheretmpdir')
echo "Test dir: \"$temp_dir\""

# test
test "$temp_dir"
local -i -r test_exit_code="$?"
echo "Test exit code: $test_exit_code"

# cleanup
rm -rf "$temp_dir"
echo "Cleaned \"$temp_dir\""
exit "$test_exit_code"
}

get_absolute_sut_path()
{
local -r current_dir="$(pwd)"
local -r relative_script_dir=$(dirname "$0")
local -r absolute_script_dir="$current_dir/$relative_script_dir"
local -r script_dir="$absolute_script_dir/../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/bump-npm-version.sh"
echo "$script_path"
run_test test
}

print_package_json() {
Expand Down
50 changes: 50 additions & 0 deletions tests/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#!/usr/bin/env bash

readonly SELF_DIRECTORY=$(dirname "$0")


main() {
local succeeded_tests=()
local failed_tests=()
local -i test_index=0

# Run
files=$(find "$SELF_DIRECTORY" -name "*.test.sh")
for file in $files; do
((test_index++))
echo "$test_index. Testing: $file"
local output
if output=$(bash "$file" 2>&1); then
succeeded_tests+=("$file")
echo $'\t'"🟢 Succeeded."
else
failed_tests+=("$file")
echo $'\t'"🔴 Failed."
fi
# shellcheck disable=SC2001
echo "$output" | sed 's/^/\t/' # Tab indent output
done

# Report
echo "-----------"
echo "Total test: $test_index"
local -ir total_failed="${#failed_tests[@]}"
if [ "$total_failed" -gt 0 ]; then
echo "Failed tests ($total_failed):"
printf '\t- %s\n' "${failed_tests[@]}"
else
echo "🎉 No tests are failed!"
fi
local -ir total_succeeded="${#succeeded_tests[@]}"
if [ "$total_succeeded" -gt 0 ]; then
echo "Succeeded tests ($total_succeeded):"
printf '\t- %s\n' "${succeeded_tests[@]}"
else
echo "😢 No tests are succeeded!"
fi

exit "$total_failed"
}


main
43 changes: 43 additions & 0 deletions tests/test-utilities.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/usr/bin/env bash

# Globals
readonly ABSOLUTE_SELF_DIRECTORY=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )


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"
}

# 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
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\""
exit "$test_exit_code"
}

0 comments on commit 1bdaeef

Please sign in to comment.