[CSM-469]: Add unit tests for component - #2
Open
oykukurtgoz wants to merge 2 commits into
Open
Conversation
Wrap side-effecting code in if __FILE__ == $PROGRAM_NAME, validate AC_ENV_FILE_PATH up front, and raise with context on nil/empty input in capitalize_first_char, get_gradle_task and run_command. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Cover get_env_variable, capitalize_first_char, get_gradle_task and run_command, plus missing/empty validation for every required env var. Run with ruby test/test_main.rb; coverage report printed at the end. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Team Run ID: Comment |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes CSM-469.
Adds unit tests for
main.rb.The whole PR is 510 added lines and 37 deleted ones;
main.rbaccounts for 43 added and 37 deleted, and almost all of that is re-indentation of the guarded block. Nothing in the build logic was moved or reworded — the Gradle command, artifact filtering, copying and env-file export are the same statements in the same order.Changes to
main.rbThree, all driven by the issue's prerequisite refactor and its "replace nil-unsafe access with an explicit error" requirement.
Top-level side effects are guarded. Everything after the four function definitions now sits inside a single
if __FILE__ == $PROGRAM_NAME ... endblock, with the original statement order kept. Appcircle runs the step withruby main.rb, so the guard is true there and the body executes exactly as before.require-ing the file only definesget_env_variable,capitalize_first_char,get_gradle_taskandrun_command.No
requireneeded aLoadErrorguard. All four requires (yaml,open3,fileutils,pathname) are stdlib and load in a bare Ruby, so they were left as they are.AC_ENV_FILE_PATHis validated up front.main.rbused to readENV['AC_ENV_FILE_PATH']straight intoopenat the very end, after Gradle had already run and artifacts had been copied. With the variable missing that raised a bareTypeError; with it empty, anENOENT. It now goes throughget_env_variablealongside the five other required variables, so a missing or empty value aborts before Gradle withMissing env file path.and exit 1. Both before and after, the step fails in that scenario; the difference is that it fails early and says why. Appcircle always sets this variable, so normal runs are unaffected.Nil-unsafe access raises with context. The tests uncovered three places that crashed with a bare
NoMethodError/TypeErroron nil or empty input. Each now raises anArgumentErrorthat names the function and the offending value:capitalize_first_charonnilor""(previouslynil.capitalize)get_gradle_taskonvariants == nil(previouslynil.split)run_commandon anilor blank command (previouslysystem(nil))None of these are reachable in a normal Appcircle run:
AC_VARIANTSis already validated non-empty, and the command string is always composed. The only reachable case is a variant list with an empty segment such as|debug, which failed before and still fails, now with a readable message.Tests (
test/test_main.rb)Self-executing, 42 examples, no Gemfile / Bundler —
rspecgem + Ruby stdlib only. Reuses theReadableFormatterand coverage report from CSM-230 / CSM-231.main.rbexposes four functions plus the script as a whole, and the tests cover all five surfaces:get_env_variable, in-process — returns the value when set, returnsnilfor both a missing key and an empty string, and the|| abort(...)guard it is paired with raisesSystemExitwith status 1.capitalize_first_char, in-process — capitalizes the first character, leaves the rest untouched, mutates the argument in place, handles a single character, and raisesArgumentErrorfor""andnil.get_gradle_task, in-process —assembleforapk,bundleforaab,assemblefallback for unknown andniloutput types, pipe-separated variants joined in order, flavored variants (stagingDebug→StagingDebug), nested module paths (feature:login), empty variants returning"", and the error branches:ArgumentErrorcarrying module and output type fornilvariants, and for an empty variant segment.run_command, in-process —systemis stubbed, so no real command ever runs. Happy path, the echoed@@[command]line, the exact command string forwarded tosystem,niland blank commands, and the failure branch:SystemExitwith the child's status propagated (a trivialruby -e 'exit 3'runs so$?is genuinely set), and the command line still being echoed before the exit.Open3.capture3(env, "ruby #{MAIN_RB}")— a missing and an empty case for each ofAC_MODULE,AC_VARIANTS,AC_OUTPUT_TYPE,AC_REPOSITORY_DIR,AC_OUTPUT_DIRandAC_ENV_FILE_PATH, each asserting exit 1 and theMissing ....message on stderr. Four further cases run with every required variable present and assert the composed command from the@@[command]line: the basecd <repo> && chmod +x ./gradlew && ./gradlew clean app:assembleDebugstring,AC_GRADLE_BUILD_EXTRA_ARGSappended, a relativeAC_PROJECT_PATHresolved againstAC_REPOSITORY_DIR, and an absoluteAC_PROJECT_PATHused as-is. The repository directory in those cases is a non-existent path under a tmpdir, socdfails and./gradlewis never reached.No real toolchain, network, or filesystem writes outside the tmpdir.
Coverage
The number is structural rather than a gap in the tests. Of the 55 executable lines, 23 are the requires and the four function bodies, and those are fully covered in-process. The remaining 32 are the guarded step body: environment validation, Gradle command composition,
./gradlewexecution, artifact globbing and copying, and the env-file export. That block only runs in theOpen3subprocesses, which in-process Coverage cannot see. The lines pastrun_commandcannot execute without running Gradle, which the issue rules out.Raising the figure would mean either extracting the command-composition logic into a pure function (a larger refactor than the issue's "wrap, don't move" prerequisite) or merging subprocess coverage the way CSM-448 does. Both are reasonable follow-ups; neither is in this PR.
Docs
README.mdgains a## Running testssection.🤖 Generated with Claude Code