如何通过Gradle运行Protractor测试并内置启动Selenium服务?
Absolutely! You can totally decouple your Gradle setup from local machine dependencies by leveraging npm packages directly within your project and using Gradle's built-in tools to manage the process—no more relying on system-wide command line calls. Here's a step-by-step refactor to make this work:
First, use the com.github.node-gradle.node plugin to handle Node.js installation and npm package management directly in your project. This plugin will auto-download Node.js if it's not present locally, eliminating local setup dependencies. Add this to your build.gradle:
plugins { id 'com.github.node-gradle.node' version '7.0.1' // Use the latest stable version } node { download = true // Auto-download Node.js if missing version = '20.10.0' // Specify your required Node.js version npmVersion = '10.2.3' // Match with a compatible npm version }
Create or update a package.json in your project root to define your E2E dependencies:
{ "devDependencies": { "protractor": "~7.0.0", "webdriver-manager": "~12.1.9" } }
Then add a Gradle task to install these dependencies locally:
task installProtractor(type: NpmTask) { args = ['install'] }
Instead of calling the global webdriver-manager, use the locally installed binary from node_modules. We'll add a task to start the server, wait for it to be ready, and a cleanup task to stop it after tests:
import java.net.HttpURLConnection import java.net.URL task startSeleniumServer(type: NpmTask, dependsOn: installProtractor) { args = ['run', 'webdriver-manager', 'start'] ignoreExitValue = true // Let the server run in the background doFirst { // Ensure webdriver binaries are up-to-date before starting the server project.exec { commandLine 'npm', 'run', 'webdriver-manager', 'update' } } doLast { // Wait for Selenium server to be ready (adjust timeout as needed) def seleniumUrl = new URL('http://localhost:4444/wd/hub/status') def timeout = 30000 // 30 seconds def startTime = System.currentTimeMillis() boolean serverReady = false while (!serverReady && (System.currentTimeMillis() - startTime) < timeout) { try { HttpURLConnection connection = seleniumUrl.openConnection() connection.setRequestMethod('GET') serverReady = (connection.responseCode == 200) connection.disconnect() } catch (Exception e) { // Server not ready yet, wait and retry Thread.sleep(1000) } } if (!serverReady) { throw new GradleException("Selenium server failed to start within ${timeout}ms") } } } // Cleanup task to stop Selenium server after tests task stopSeleniumServer(type: Exec) { // Linux/macOS command; replace with `taskkill /F /IM node.exe /FI "WINDOWTITLE eq webdriver-manager start"` for Windows commandLine 'pkill', '-f', 'webdriver-manager start' ignoreExitValue = true // Ignore error if server isn't running }
Modify your runProtractor task to use the local Protractor binary, and link it to the server lifecycle tasks:
task runProtractor(type: NpmTask, dependsOn: [installProtractor, startSeleniumServer]) { args = ['run', 'protractor', 'src/test/javascript/e2e/conf.js'] finalizedBy stopSeleniumServer // Ensure server stops even if tests fail }
- Protractor Config Tweak: In your
conf.js, make suredirectConnect: falseandseleniumAddress: 'http://localhost:4444/wd/hub'are set to use the local server. - Cross-Platform Compatibility: Adjust the
stopSeleniumServercommand for Windows (as noted in the code comment) or use a small Node script to kill the server cross-platform. - Caching: The Node plugin caches the downloaded Node.js version, so subsequent builds will be faster.
内容的提问来源于stack exchange,提问作者Joe

