Skip to content

Conversation

@Ethan-Arrowood
Copy link
Member

@Ethan-Arrowood Ethan-Arrowood commented Nov 4, 2025

Integration Test Overhaul

This PR introduces a comprehensive overhaul of Harper's integration testing infrastructure, enabling concurrent test execution for faster feedback cycles and improved developer productivity.

Overview of Changes

New Integration Test Framework:

  • Created a new integration test framework based on Node.js Test Runner with full support for concurrent test execution
  • Implemented loopback address pooling to enable true test isolation - each test file gets its own Harper instance on a unique network address
  • Added comprehensive utilities for Harper lifecycle management (setupHarper, teardownHarper) with automatic resource cleanup
  • Introduced new test structure requirements: test files must be independent, hermetic, and deterministic

Documentation:

CI/CD Improvements:

  • Replaced single integration test workflow with new parallelized workflow supporting test sharding across multiple runners
  • Build artifacts are now cached and reused across test jobs for faster execution
  • Added support for selective Node.js version testing and test sharding (1/4, 2/4, 3/4, 4/4)
  • Separated legacy API tests from new integration tests with dedicated workflows

New Test Infrastructure:

  • Implemented loopback address pool manager for concurrent test execution without port conflicts
  • Created reusable Harper lifecycle utilities with configurable installation directories and network settings
  • Added helper utilities for tar.gz compression, required for application deployment tests
  • Included setup script for configuring loopback addresses on macOS and Linux

Example Tests:

Additional Changes:

  • Updated ESLint config to allow floating promises in test files for async test functions
  • Fixed minor issues in logging and user utilities for better compatibility

How to Review

  1. Start with the documentation - Read integrationTests/README.md to understand the new testing philosophy, requirements, and execution strategies. This provides critical context for all other changes.

  2. Review the utilities - Check integrationTests/utils/README.md and the utility implementations in integrationTests/utils/ to understand the building blocks available for writing tests.

  3. Examine the test examples - Look at the deploy tests (deploy-from-source.test.mts and deploy-from-github.test.mts) as reference implementations showing how to use the new framework and utilities.

  4. Review CI/CD changes - Check .github/workflows/integration-tests.yml to understand how tests are parallelized across runners and how sharding works.

  5. Check supporting changes - Review smaller changes to source files (installer, logging, etc.) that support better test isolation and execution.

Testing

The new integration tests require loopback address configuration. Run the setup script if needed:

bash integrationTests/utils/scripts/setup-loopback.sh

Then execute tests:

npm run test:integration

@Ethan-Arrowood Ethan-Arrowood changed the base branch from main to harper-application-lock November 4, 2025 23:41
Base automatically changed from harper-application-lock to main November 5, 2025 15:12
@Ethan-Arrowood Ethan-Arrowood force-pushed the integration-test-overhaul branch 2 times, most recently from 142ee12 to 4f817ad Compare November 21, 2025 21:30
Comment on lines +50 to +55
// const harperAppLock = await readFile(join(ctx.harper.installDir, 'harper-application-lock.json'), 'utf-8');
// deepStrictEqual(JSON.parse(harperAppLock), {
// applications: {
// 'test-application': {}
// }
// });
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I need to cherry-pick the recent application lock fix to this repo and then I can uncomment this assertion.

@Ethan-Arrowood Ethan-Arrowood marked this pull request as ready for review November 21, 2025 21:39
@Ethan-Arrowood Ethan-Arrowood requested a review from a team as a code owner November 21, 2025 21:39
@Ethan-Arrowood Ethan-Arrowood requested review from a team and removed request for a team November 21, 2025 21:40
Copy link
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks like it will be awesome, excited to see more tests brought in!

@heskew
Copy link
Member

heskew commented Dec 2, 2025

Generally this is pretty awesome and most of the feedback I've thought of would be non-blocking edge case handling and 'nice to haves' (e.g. loopback cleanup - i.e. leave no trace).

This (test utils especially) might be nice for others to use in their own Harper apps and components/plugins. Have you thought about publishing as a separate package?

Copy link
Contributor

@cb1kenobi cb1kenobi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks really awesome! Great job!

Comment on lines +176 to +181
const parts = address.split('.');
if (parts.length !== 4 || parts[0] !== '127' || parts[1] !== '0' || parts[2] !== '0') {
throw new InvalidLoopbackAddressError(address);
}

const index = parseInt(parts[3], 10) - 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could use a regex instead of splitting.

Suggested change
const parts = address.split('.');
if (parts.length !== 4 || parts[0] !== '127' || parts[1] !== '0' || parts[2] !== '0') {
throw new InvalidLoopbackAddressError(address);
}
const index = parseInt(parts[3], 10) - 1;
const m = address.match(/^127\.0\.0\.(\d{1,3})$/);
if (!m?.[1]) {
throw new InvalidLoopbackAddressError(address);
}
const index = Number.parseInt(m[1], 10) - 1;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I'm not a huge fan of using regex due to its readability. I understand it can be better performance but since this is just a util script I don't think I'm going to make this change.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I was thinking the regex was so simple that it would be more readable than the split version.

@Ethan-Arrowood
Copy link
Member Author

#51 will fix the failing format check

Copy link
Member

@kriszyp kriszyp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work, let's start using it!

@Ethan-Arrowood Ethan-Arrowood force-pushed the integration-test-overhaul branch from 71bea0e to f5af665 Compare December 3, 2025 22:47
- New integration test guidelines and framework
- Updated GitHub Actions workflow
- Continue to support existing integration tests
- Copious documentation and utility scripts
@Ethan-Arrowood Ethan-Arrowood force-pushed the integration-test-overhaul branch from f5af665 to 3a3e0eb Compare December 3, 2025 22:48
@Ethan-Arrowood Ethan-Arrowood merged commit bd0424b into main Dec 3, 2025
19 checks passed
@Ethan-Arrowood Ethan-Arrowood deleted the integration-test-overhaul branch December 3, 2025 23:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants