如何在Docker容器中运行TestCafe测试?解决/bin/sh浏览器识别错误
本地通过TestCafe的runner或CLI执行测试一切正常,但在基于testcafe/testcafe镜像构建的容器中运行时,出现以下错误:
ERROR Cannot find the browser. "/bin/sh" is neither a known browser alias, nor a path to an executable file.
相关配置如下:
Dockerfile
FROM testcafe/testcafe USER root WORKDIR /app COPY package*.json . RUN npm install --force --legacy-peer-deps --progress=false CMD npm run testrunner # this is a command that i define in package.json
package.json
{ ... "main": "index.js", "scripts": { "cafe:prod:h:3": "npx testcafe 'chrome:headless' --concurrency 3 src/tests/masterdata", "testrunner": "node runner.js" }, ... "dependencies": { "@aws-sdk/client-ssm": "^3.535.0", "aws-sdk": "^2.1582.0", "dotenv": "^16.4.5", "downloads-folder": "^3.0.3", "testcafe": "^3.5.0", "testcafe-browser-tools": "^2.0.26" } }
runner.js
const createTestCafe = require('testcafe'); (async function () { const testcafe = await createTestCafe(); try { const runner = testcafe.createRunner(); const failed = await runner.src(['src/tests/masterdata']).browsers('chrome:headless').concurrency(3).run(); console.log('Tests failed: ' + failed); } finally { await testcafe.close(); } })();
疑问:代码中并未引用/bin/sh,为何TestCafe会尝试使用该路径?如何在容器内正常运行runner.js?
这个错误是因为容器环境中,TestCafe的浏览器检测逻辑被npm脚本的shell执行方式干扰。当用npm run testrunner启动脚本时,npm会用/bin/sh包裹node命令,TestCafe内部检测机制误将这个shell进程当成浏览器启动目标路径,从而抛出错误。
有两种可行的解决方案:
方案1:绕过npm脚本的shell包裹,直接用node命令启动
修改Dockerfile的CMD指令,直接执行node命令:
CMD ["node", "runner.js"]
这种方式让TestCafe直接识别浏览器配置,不会被npm的shell进程干扰。
方案2:在runner中指定Chrome的绝对路径
testcafe/testcafe镜像中Chrome的默认路径是/usr/bin/google-chrome,可以在runner.js中直接指定该路径并添加headless参数:
const failed = await runner.src(['src/tests/masterdata']) .browsers('/usr/bin/google-chrome --headless') .concurrency(3) .run();
直接指定浏览器可执行文件,避免TestCafe自动检测出错。
额外验证:用CLI命令测试可用性
可以先替换Dockerfile的CMD为CLI命令,验证容器内Chrome是否正常:
CMD ["npx", "testcafe", "chrome:headless", "--concurrency", "3", "src/tests/masterdata"]
如果该命令能正常运行,说明问题确实出在npm脚本的shell包裹上,再切换回runner的解决方案即可。
内容的提问来源于stack exchange,提问作者İbrahim Akar

