我试图将我的角E2E测试扩展到。简而言之,我创建了一个docker-compose.test.yml文件:
version: "3.4"
services:
# set up angular app
angular:
build:
context: ./frontend
dockerfile: sample.Dockerfile
target: test
image: angular:test
container_name: angular
ports:
- "4200:4200"
depends_on:
- nodejs
command: npm run e2e -- --protractor-config=e2e/protractor-docker.conf.js --host 0.0.0.0
nodejs:
build:
context: ./backend
dockerfile: Dockerfile
target: development
image: nodejs:dev
container_name: nodejs
ports:
- "3000:3000"
networks:
- backend
depends_on:
- db
restart: always
# the mongo database
db:
image: mongo
container_name: db
networks:
- backend
ports:
- "27017:27017"
networks:
backend:
driver: bridge
对于量角配置,我遵循此链接中找到的教程:
travis ci
的角度教程我必须进行一些调整,因此:
let config = require('./protractor.conf').config;
// Tell protrator where the chrome driver is
// https://gitlab.com/dasch8/angular-ci/
// https://hub.docker.com/r/weboaks/node-karma-protractor-chrome/
config.chromeDriver = "/usr/bin/chromedriver";
config.allScriptsTimeout = 60000;
config.getPageTimeout = 60000;
config.jasmineNodeOpts.defaultTimeoutInterval = 60000;
// have it connect to the angular app
// config.baseUrl = "http://angular:4200";
config.capabilities = {
browserName: 'chrome',
chromeOptions: {
args: ['--headless', '--no-sandbox', '--disable-gpu']
},
};
exports.config = config;
使用配置,E2E测试在我的本地计算机上取得了成功。但是,当我在.travis.yml的脚本中运行此内容时:
before_script:
- docker-compose -f docker-compose.test.yml build
script:
- docker-compose -f docker-compose.test.yml run --name angular -p 4200:4200 angular
Travis CI失败。输出为:
- Error: Timeout - Async callback was not invoked within timeout specified by jasmine.DEFAULT_TIMEOUT_INTERVAL.
- Failed: Timed out waiting for asynchronous Angular tasks to finish after 60 seconds. This may be because the current page is not an Angular application. Please see the FAQ for more details: https://github.com/angular/protractor/blob/master/docs/timeouts.md#waiting-for-angular
这很奇怪,因为我写了:
import { AppPage } from './app.po';
// Test bed
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display navbar with title', () => {
page.navigateTo().then(() => {
console.log('Successfully connected to the page');
});
expect(page.getHeaderText()).toEqual('hobbies');
});
});
以及在Travis CI的日志中,日志打印出来:
成功连接到页面。其余的日志在这里找到:
我的travis ci日志
我不确定我在做什么错。测试通过我当地的机器太奇怪了。我试图通过使用硒/轮毂和硒/节点 - 铬片图像来以不同的方式解决此问题,并将量角器连接到该硒服务器。这是同一故事。我让它在本地机器上工作,但在Travisci失败了。我将在另一个问题中询问硒问题。
我遵循C.Peck的答案。我在本地机器上进行了测试,并奏效了。但是,如我的日志中所示,它仍然在Travisci中不起作用:
travisci日志。
我什至将等待时间设置为11秒,测试仍然失败。然后,我将protractor-docker.conf.js
中的allScriptsTimeout
增加到180000。这样做后,测试通过了:
成功的角度E2E测试的Travis CI日志
但是,测试需要2分10秒才能完成。这很令人沮丧,因为我只是在检查标题是否出现在Navbar中。恐怕我要测试诸如表单和单击按钮之类的内容,Travis CI甚至可能需要更长的时间。
最终解决了!!!因此,我找到了这个链接,我汲取了一些灵感:Chrome在Docker Network中不可到达
幸运的是,个人使用的配置几乎相同,但是有趣的部分是个人正在反向其Web应用程序。
我也做了同样的事情:
#default.conf for proxy service
upstream docker-web {
#docker angular container
server angular:4200;
}
upstream docker-node {
#docker nodejs container
server nodejs:3000;
}
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://docker-web;
#proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
add_header X-Upstream $upstream_addr;
}
location /api {
proxy_pass http://docker-node;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
add_header X-Upstream $upstream_addr;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
以及我在nginx上托管的Angular Web应用程序:
server {
listen 4200;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
我使用我的Angular图像为量角器创建了一个单独的容器,我将提供:
###################
## builder ##
###################
FROM node:10-alpine AS builder
RUN mkdir -p /usr/src/frontend
WORKDIR /usr/src/frontend
COPY package.json /usr/src/frontend
RUN npm cache clean --force
&& npm install
COPY . /usr/src/frontend
RUN npm run build -- --prod
##################
## production ##
##################
FROM nginx:alpine AS production
COPY --from=builder /usr/src/frontend/dist/frontend /usr/share/nginx/html
COPY --from=builder /usr/src/frontend/nginx/default.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
#################
## development ##
#################
# because development uses the same stuff from builder image
FROM builder AS development
EXPOSE 4200
CMD ["npm", "start"]
##################
## test ##
##################
# because test uses the same stuff from builder image
FROM builder AS test
RUN apk update &&
apk upgrade &&
apk add --no-cache chromium nss chromium-chromedriver
EXPOSE 9876
ENV CHROME_BIN /usr/bin/chromium-browser
# just needed the chromedriver!!!
# https://github.com/angular/angular-cli/issues/5019
# https://gitlab.com/dasch8/angular-ci/blob/master/README.md
CMD [ "npm", "run", "test", "--", "--no-watch", "--no-progress", "--browsers=ChromeHeadlessCI"]
FROM production
然后,我也创建了硒网格服务和Chrome节点服务。Docker Selenium的文档在这里找到:
Docker Selenium
我的错误是主机名(Docker-Compose文件中的容器/服务名称)无法正确解决,因为它们不在同一网络上。由于量角器连接到硒,硒可以处理E2E测试,因此browser.get('http://proxy')
找不到Angular应用,因为硒与代理容器不在同一网络上。然后,我删除了我在Docker-Compose文件中使用的所有网络,并制作了一个新的Docker-Compose文件,其中包括我的Selenium Grid Service(称为Selenium-Hub),Selenium/node-chrome Service(称为Chrome_node),平均堆栈(Angular),nodejs,db)和protractor服务(通过从Docker文件中定位测试构建)。
我的docker-compose.selenium.yml文件:
version: '3.4'
services:
selenium-hub:
image: selenium/hub:3.141.59
container_name: selenium-hub
environment:
- GRID_TIMEOUT=10000
ports:
- "4444:4444"
privileged: true
#tty: true
chrome_node:
image: selenium/node-chrome:3.141.59
volumes:
- /dev/shm:/dev/shm
container_name: chrome_node
environment:
- HUB_PORT_4444_TCP_ADDR=selenium-hub
- HUB_PORT_4444_TCP_PORT=4444
ports:
- "5555:5555"
privileged: true
depends_on:
- selenium-hub
#tty: true
proxy:
build:
context: ./proxy
dockerfile: Dockerfile
image: proxy
container_name: proxy
# HOST:CONTAINER
ports:
- "80:80"
#tty: true
depends_on:
- angular
angular:
build:
context: ./frontend
dockerfile: sample.Dockerfile
target: production
image: angular:prod
container_name: angular
ports:
- "4200:4200"
privileged: true
depends_on:
- nodejs
#tty: true
nodejs:
build:
context: ./backend
dockerfile: Dockerfile
target: development
image: nodejs:dev
container_name: nodejs
ports:
- "3000:3000"
depends_on:
- db
restart: always
#tty: true
# the mongo database
db:
image: mongo
container_name: db
ports:
- "27017:27017"
#tty: true
protractor:
build:
context: ./frontend
dockerfile: sample.Dockerfile
target: test
image: angular:test
container_name: protractor
ports:
- "9876:9876"
privileged: true
depends_on:
- selenium-hub
- chrome_node
#tty: true --> not neccesary
command: npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js --webdriver-update=false --dev-server-target=
这是我的新量角构型文件:
let config = require('./protractor.conf').config;
// do not use the chromeDriver. If you do, it will not connect to Selenium service
config.directConnect = false;
// have it connect to the angular app
config.baseUrl = "http://proxy";
// Protractor getting the page-timeout
config.getPageTimeout = 60000;
// Selenium Webdriver timeout
config.allScriptsTimeout = 60000;
// Jasmine test script timeout
config.jasmineNodeOpts.defaultTimeoutInterval = 60000;
config.seleniumAddress = 'http://selenium-hub:4444/wd/hub'
config.capabilities = {
browserName: 'chrome',
chromeOptions: {
args: ['--headless', '--disable-gpu', '--no-sandbox'],
},
};
标志--dev-server-target=
让我们知道不要启动NG服务(因为我们正在nginx中启动Angular App)。这样做之后,我的测试通过了!!!而且,我将暂停设置为60000,测试通过了3秒,这是一个很大的改进!!!!:)
我在.travis.yml中使用的脚本:
before_script:
- docker-compose -f docker-compose.selenium.yml build
script:
- docker-compose -f docker-compose.selenium.yml up -d chrome_node proxy
- docker container ls
- docker-compose -f docker-compose.selenium.yml up protractor
对于网络,docker-compose up
命令将其本身处理,Docker的DNS Resolver将解析主机名(Docker-Compose文件中的我们的容器/服务名称)。有关Docker组成网络的更多信息,请参见Docker的文档:Docker组成和网络
这是构建的日志:
travis ci logs
我希望将来对任何人有所帮助:)
那么,添加等待是否如下影响吗?
import { AppPage } from './app.po';
// Test bed
describe('workspace-project App', () => {
let page: AppPage;
beforeEach(() => {
page = new AppPage();
});
it('should display navbar with title', () => {
page.navigateTo().then(() => {
console.log('Successfully connected to the page');
});
browser.ignoreSynchronization = true
driver.wait(function () {
return driver.isElementPresent(page.getHeaderText('hobbies'));
}, timeout);
expect(page.getHeaderText()).toEqual('hobbies');
browser.ignoreSynchronization = false;
});
});