Skip to content

How to Run Unit Tests and Capture Results in Batch Script

Learn how to execute unit tests from .NET, Python, Node.js, and Java in Batch Scripts, capture exit codes, log results, and integrate with CI/CD pipelines for automated testing workflows.

Automated testing is a cornerstone of reliable software development. Running unit tests from a Batch Script and capturing the results enables continuous integration workflows, pre-commit validation, build pipeline gates, and rapid feedback loops. Whether you are working with .NET, Java, Python, Node.js, or any other testing framework, a Batch Script can orchestrate test execution, collect results, and take action based on pass or fail outcomes.

In this guide, we will explore how to run unit tests from various frameworks and capture their results using Batch Script, including return code checks, output logging, and result parsing.

Understanding Test Exit Codes

Most test runners follow a standard convention:

Exit Code Meaning
0 All tests passed
1 or non-zero One or more tests failed
2 Test runner error (configuration, missing files)

Batch scripts use %errorlevel% to capture the exit code after running the test command.

Method 1: Running .NET Tests (dotnet test)

@echo off
setlocal

set "project=MyApp.Tests"

:: Generate locale-safe timestamp for the log filename
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "logfile=test_results_%dt:~0,4%%dt:~4,2%%dt:~6,2%.log"

echo =============================================
echo   RUNNING UNIT TESTS: %project%
echo   %date% %time:~0,8%
echo =============================================
echo.

:: Run tests and capture output
dotnet test "%project%" --no-build --verbosity normal > "%logfile%" 2>&1
set "test_result=%errorlevel%"

:: Display results
type "%logfile%"

echo.
echo =============================================
if %test_result%==0 (
    echo   RESULT: ALL TESTS PASSED
) else (
    echo   RESULT: TESTS FAILED (exit code: %test_result%^)
)
echo   Log: %logfile%
echo =============================================

exit /b %test_result%

Generating a TRX Report

dotnet test MyApp.Tests --logger "trx;LogFileName=results.trx" --results-directory TestResults

This creates an XML-based .trx report that can be consumed by CI/CD tools like Azure DevOps.

Method 2: Running Python Tests (pytest)

@echo off
setlocal

set "test_dir=tests"
set "logfile=pytest_results.log"

echo Running Python tests...
echo.

:: Run pytest with verbose output and JUnit XML
python -m pytest "%test_dir%" -v --tb=short --junitxml=test_report.xml > "%logfile%" 2>&1
set "test_result=%errorlevel%"

type "%logfile%"

echo.
if %test_result%==0 (
    echo [PASSED] All tests passed.
) else (
    echo [FAILED] Some tests failed. Exit code: %test_result%
)

exit /b %test_result%

Method 3: Running Node.js Tests (npm test)

@echo off
setlocal

set "logfile=npm_test_results.log"

echo Running Node.js tests...
echo.

:: npm test typically runs the "test" script from package.json
call npm test > "%logfile%" 2>&1
set "test_result=%errorlevel%"

type "%logfile%"

echo.
if %test_result%==0 (
    echo [PASSED] All tests passed.
) else (
    echo [FAILED] Tests failed. Exit code: %test_result%
)

exit /b %test_result%

Method 4: Running Java Tests (Maven)

@echo off
setlocal

set "logfile=maven_test_results.log"

echo Running Java unit tests...
echo.

call mvn test -B > "%logfile%" 2>&1
set "test_result=%errorlevel%"

:: Extract summary from Maven output
echo.
echo Test Summary:
findstr /i "Tests run:" "%logfile%"

echo.
if %test_result%==0 (
    echo [PASSED] All tests passed.
) else (
    echo [FAILED] Tests failed.
)

exit /b %test_result%

Method 5: Universal Test Runner with Result Capture

A generic test runner that works with any command and provides structured output:

@echo off
setlocal enabledelayedexpansion

:: Configuration
set "test_command=dotnet test MyApp.Tests --no-build -v normal"
set "project_name=MyApp"
set "log_dir=TestLogs"

:: Create log directory
if not exist "%log_dir%" mkdir "%log_dir%"

:: Generate timestamped log filename
for /f "tokens=2 delims==" %%T in ('wmic os get LocalDateTime /value') do set "dt=%%T"
set "timestamp=%dt:~0,4%%dt:~4,2%%dt:~6,2%_%dt:~8,2%%dt:~10,2%%dt:~12,2%"
set "logfile=%log_dir%\%project_name%_%timestamp%.log"

echo =============================================
echo   TEST EXECUTION
echo   Project:   %project_name%
echo   Command:   %test_command%
echo   Log:       %logfile%
echo   Started:   %date% %time:~0,8%
echo =============================================
echo.

:: Record start time
set "start_time=%time%"

:: Execute tests (call ensures .cmd wrappers like npm/mvn don't terminate the script)
call %test_command% > "%logfile%" 2>&1
set "test_result=!errorlevel!"

:: Record end time
set "end_time=%time%"

:: Display results
echo.
echo =============================================
echo   TEST RESULTS
echo =============================================
echo.
echo   Exit Code:   !test_result!
echo   Started:     %start_time%
echo   Finished:    %end_time%

if !test_result!==0 (
    echo   Status:      PASSED
    echo.
    echo   [OK] All tests passed successfully.
) else (
    echo   Status:      FAILED
    echo.
    echo   [ERROR] Test failures detected.
    echo.
    echo   Failed test output (last 30 lines^):
    echo   -----------------------------------
    powershell -NoProfile -Command "Get-Content '%logfile%' | Select-Object -Last 30"
)

echo.
echo   Full log: %logfile%
echo =============================================

exit /b !test_result!

Pre-Commit Test Gate

Run tests before allowing a git commit:

@echo off
setlocal

echo [PRE-COMMIT] Running tests before commit...
echo.

:: Run the test suite
call npm test >nul 2>&1
set "result=%errorlevel%"

if %result%==0 (
    echo [OK] Tests passed. Proceeding with commit.
    exit /b 0
) else (
    echo [BLOCKED] Tests failed! Fix failures before committing.
    echo.
    echo Run "npm test" to see details.
    exit /b 1
)

Build Pipeline Integration

A complete build script that runs tests as part of the deployment pipeline:

@echo off
setlocal

echo =============================================
echo   BUILD PIPELINE
echo =============================================
echo.

:: Stage 1: Build
echo [1/3] Building...
dotnet build -c Release > build.log 2>&1
if %errorlevel% neq 0 (
    echo [FAIL] Build failed!
    type build.log
    exit /b 1
)
echo       Build succeeded.

:: Stage 2: Test
echo [2/3] Running tests...
dotnet test --no-build -c Release --logger "trx" > test.log 2>&1
set "test_result=%errorlevel%"

if %test_result% neq 0 (
    echo [FAIL] Tests failed!
    type test.log
    exit /b 1
)
echo       All tests passed.

:: Stage 3: Package
echo [3/3] Creating package...
dotnet publish -c Release -o publish > publish.log 2>&1
if %errorlevel% neq 0 (
    echo [FAIL] Publish failed!
    type publish.log
    exit /b 1
)
echo       Package ready in: publish\

echo.
echo =============================================
echo   PIPELINE COMPLETE - Ready to deploy
echo =============================================

Common Mistakes

The Wrong Way: Not Checking the Exit Code

:: WRONG - Ignores whether tests passed or failed
dotnet test MyApp.Tests
echo "Tests done, deploying..."
:: Deploys even if tests failed!

Output Concern: Without checking %errorlevel%, the script continues even after test failures, potentially deploying broken code. Always check the exit code and halt the pipeline on failure.

The Wrong Way: Using npm Without CALL

:: WRONG - Script terminates after npm finishes
npm test
echo This line never executes

npm.cmd is a Batch file itself. Running it without call causes the current script to terminate when npm finishes. Always use call npm test.

Best Practices

  1. Always check %errorlevel%: Gate subsequent actions (deploy, commit, package) on test success.
  2. Log output to files: Capture test output for debugging and historical records.
  3. Generate structured reports: Use TRX (.trx), JUnit XML, or similar formats for CI/CD integration.
  4. Use call for .cmd/.bat tools: npm, Maven, and other tools wrapped in Batch files require call.
  5. Show failure details: On failure, display the last few lines of output to help diagnose the issue without opening the full log.

Conclusion

Running unit tests and capturing results from a Batch Script is a straightforward pattern: execute the test command, capture the exit code with %errorlevel%, redirect output to a log file, and take action based on pass or fail. This pattern works identically across .NET, Python, Node.js, Java, and any other test framework that follows the standard exit code convention. By integrating test execution into build scripts, pre-commit hooks, and deployment pipelines, teams ensure that code quality gates are enforced automatically at every stage of the development workflow.

Navigation