如何用Protractor非阻塞执行Shell脚本并实现步骤顺序执行?
Let's tackle both of your questions with practical, scalable solutions tailored to Protractor's Node.js environment:
1. Non-blocking Shell Script Execution in Protractor
Since Protractor runs on Node.js, you can leverage Node's built-in child_process module to run shell scripts non-blockingly while still tracking their completion. The key is wrapping execution in a Promise so you can use async/await to control flow when needed.
Here's a reusable function for promise-based shell script execution:
const { exec } = require('child_process'); const util = require('util'); // Promisify the exec function to work with async/await const execAsync = util.promisify(exec); async function runShellScript(scriptPath) { try { const { stdout, stderr } = await execAsync(`bash ${scriptPath}`); console.log('Script output:', stdout); if (stderr) { console.warn('Script warnings:', stderr); } } catch (error) { console.error('Failed to run script:', error); throw error; // Propagate error to trigger Protractor test failure if needed } }
This runs scripts non-blockingly by default, but the promise lets you wait for completion whenever you need to enforce execution order—perfect for your second issue.
2. Enforcing Sequential Build & Launch Steps
Your core problem was asynchronous shell commands running out of order, with afterEach being a rigid workaround. Here are two flexible, scalable fixes:
Option 1: Use async/await in Protractor Hooks
Leverage Protractor's beforeAll hook (or a dedicated setup step) to explicitly sequence your build and launch operations. This ensures step 1 finishes before step 2 starts:
describe('Application Test Workflow', () => { beforeAll(async () => { // Step 1: Run Selenium code to build the app (wrap this in a promise if it's async) await buildApplication(); // Step 2: Execute your .sh file to download and launch the app await runShellScript('./path/to/your/launch-script.sh'); }); it('should verify the app is running correctly', () => { // Your test assertions here }); });
Make sure your buildApplication function returns a Promise if it handles async operations (like API calls or shell-based build commands). The await keyword will force Protractor to wait for it to complete before moving to the script execution.
Option 2: Combine Steps in a Single Shell Script
If your build process can be run via shell commands, consolidate both steps into one .sh file to enforce sequential execution at the shell level. This reduces extra Node.js code for flow management:
build-and-launch.sh
#!/bin/bash # Step 1: Build the application (replace with your actual build command) npm run build --prod # Step 2: Download and launch the application ./download-and-start-app.sh
Then call this combined script from Protractor:
beforeAll(async () => { await runShellScript('./build-and-launch.sh'); });
This approach is clean and scalable—you can add more steps to the shell script later without modifying your Protractor code.
Why This Beats afterEach
Using beforeAll or explicit async/await steps gives you full control over when operations run (e.g., once before all tests, or before specific test suites). Unlike afterEach, which runs after every test case, this method is flexible and easy to extend as your workflow grows.
内容的提问来源于stack exchange,提问作者Siddharth Joshi

