#testing #jestjs #continuous-integration #nestjs #circleci
#тестирование #jestjs #непрерывная интеграция #nestjs #circleci
Вопрос:
У меня есть приложение nestjs, в котором есть набор тестов jest e2e. Запуск его локально занимает примерно 13 секунд ~. Однако при попытке запустить их на circleci тесты зависают и, похоже, не завершаются успешно. Они истекают через 10 минут и завершаются сбоем. Я не уверен, что вызывает такое поведение.
/.circleci/config.yml
version: 2.1
jobs:
run_tests:
docker:
- image: circleci/node:10
steps:
- checkout #cloning git repo
- run:
name: Install npm dependencies
command: |
npm install --save
- run:
name: Run unit tests
command: |
NODE_ENV=test amp;amp; node node_modules/.bin/jest
environment:
DATABASE_URL: postgres://_:_:@localhost:5432/testdb
- run:
name: Run e2e tests
command: |
NODE_ENV=test amp;amp; node --inspect-brk node_modules/.bin/jest --runInBand --config ./test/jest-e2e.json --watchAll=false
environment:
DATABASE_URL: postgres://_:_:@localhost:5432/testdb
- store_test_results:
path: test-results
workflows:
build_test:
jobs:
- run_tests
test/jest-e2e.json
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^. \.(t|j)s$": "ts-jest"
},
"verbose": true
}
настройка тестирования
beforeAll(async () => {
const rootModule: TestingModule = await Test.createTestingModule({
imports: [RootModule]
}).compile();
app = rootModule.createNestApplication();
await app.init();
shopboxService = app.select(ShopboxModule).get(ShopboxService);
clothesService = app.select(ClothesModule).get(ClothesService);
await shopboxService.deleteTags();
});
it('authenticates a user and includes a jwt token in the response', async () => {
const response = await request(app.getHttpServer())
.post('/auth/login')
.send({ email: 'myemail@example.com', password: '123456789' })
.expect(201);
adminAccessToken = response.body.token;
expect(adminAccessToken).toMatch(
/^[A-Za-z0-9-_=] .[A-Za-z0-9-_=] .?[A-Za-z0-9-_. /=]*$/
);
});
разборка теста
afterAll(async () => {
try {
await shopboxService.deleteTags();
} catch (e) {
console.warn('error', e);
} finally {
await app.close();
}
});
После удаления —inspect-brk circleci начал предоставлять обратную связь по результатам тестов.
FAIL test/user-store-reservation-flow.e2e-spec.ts (37.493 s)
User create store reservation flow
✕ authenticates a user and includes a jwt token in the response (2 ms)
✕ authenticates a user and includes a jwt token in the response
✕ creates a user
✕ creates a reservation, check that it exists in shopbox (4 ms)
✕ create clothing on storeReservation, check that it has the right properties
✕ check that clothing exists in shopbox, and has correct price, barcode, user, tag and reservation (1 ms)
✕ fails when persisting another one, should not persist to shopbox
✕ updating shopbox stock should retrieve stock 1
✕ get current reservations should return 1 (1 ms)
✕ should not be able to create a second reservation
✕ delete clothing should fail on user, but be accepted as employee
✕ delete clothing should fail on user, but be accepted as employee
✕ create a new piece of clothing and assert that it exists in the db and shopbox (1 ms)
✕ delete reservation and check that the clothing and reservation is terminated in postgres and does not exist in shopbox
● User create store reservation flow › authenticates a user and includes a jwt token in the response
Timeout - Async callback was not invoked within the 30000 ms timeout specified by jest.setTimeout.Error: Timeout - Async callback was not invoked within the 30000 ms timeout specified by jest.setTimeout.
at mapper (../node_modules/jest-jasmine2/build/queueRunner.js:27:45)
● User create store reservation flow › authenticates a user and includes a jwt token in the response
TypeError: Cannot read property 'getHttpServer' of undefined
38 |
39 | it('authenticates a user and includes a jwt token in the response', async () => {
> 40 | const response = await request(app.getHttpServer())
| ^
41 | .post('/auth/login')
42 | .send({ email: '_', password: '123456789' })
43 | .expect(201);
at Object.it (user-store-reservation-flow.e2e-spec.ts:40:40)
Я не уверен, почему это не удается, поскольку оно работает, как и ожидалось, локально.
Также после запуска тестов кажется, что соединение с базой данных не отключается должным образом
Time: 37.537 s
Ran all test suites.
[Nest] 624 - 11/21/2020, 12:37:07 AM [ExceptionHandler] Unable to connect to the database. Retrying (1)...
Jest did not exit one second after the test run has completed.
This usually means that there are asynchronous operations that weren't stopped in your tests. Consider running Jest with `--detectOpenHandles` to troubleshoot this issue.
[Nest] 624 - 11/21/2020, 12:37:40 AM [ExceptionHandler] Unable to connect to the database. Retrying (2)... 33005ms
[Nest] 624 - 11/21/2020, 12:38:13 AM [ExceptionHandler] Unable to connect to the database. Retrying (3)... 33007ms
[Nest] 624 - 11/21/2020, 12:38:46 AM [ExceptionHandler] Unable to connect to the database. Retrying (4)... 33004ms
[Nest] 624 - 11/21/2020, 12:39:19 AM [ExceptionHandler] Unable to connect to the database. Retrying (5)... 33005ms
[Nest] 624 - 11/21/2020, 12:39:52 AM [ExceptionHandler] Unable to connect to the database. Retrying (6)... 33006ms
Комментарии:
1. Эй, Джонас, тебе это нужно
--inspect-brk
в твоей команде CI? Также время ожидания, похоже, является настройкой по умолчанию для CircleCI, а не для jest.2. @IvanSantos Я не думаю, что знаю, я думаю, что добавил его для отладки некоторое время назад. Я удалил его и снова запустил конвейер
3. @IvanSantos на самом деле это имело огромное значение, теперь circleci предоставляет тестовую информацию!
4. похоже, ваши тесты не могут подключиться к базе данных. Проверьте конфигурации для этого.
5. @IvanSantos да, я подозреваю, что это монго, поскольку приложение использует это для журналов. Я должен возиться с
config.yml
, я полагаю
Ответ №1:
Было несколько ошибок. Вначале он зависал, потому --inspect-brk
что, потому что он устанавливает точку останова для отладки в начале программы.
Затем я столкнулся с несколькими ошибками в двух моих базах данных postgres и mongodb. Они либо зависли, либо не смогли подключиться должным образом.
Чтобы заставить его работать, мне пришлось
- Настройте образ Mongodb в контейнере
- Настройте изображение Postgres в контейнере
- Установите расширения для postgres
- Удалите инкапсулирующую транзакцию в сценарии заполнения.
.circleci/config.yml
version: 2.1
jobs:
run_tests:
docker:
- image: circleci/node:10
- image: circleci/postgres:9.6.8-alpine-postgis
auth:
username: ?
password: ? # context / project UI env-var reference
environment:
POSTGRES_USER: ?
POSTGRES_DB: ?
POSTGRES_PASSWORD: ?
- image: circleci/mongo:4.4.1
environment:
DATABASE_URL: mongodb://localhost/?
steps:
- checkout #alias for git clone
- run:
name: Installing psql client
command: |
sudo apt install postgresql-client
- run:
name: Waiting for PostgreSQL to start
command: |
for i in `seq 1 10`;
do
nc -z localhost 5432 amp;amp; echo Success amp;amp; exit 0
echo -n .
sleep 2
done
echo Failed waiting for Postgres amp;amp; exit 1
- run:
name: Installing postgres contributions
command: |
sudo apt-get -qq update
sudo apt-get -qq install postgresql-contrib
- run:
name: Restarting postgres
command: |
sudo service postgresql restart
- run:
name: Install extensions for postgres
command: |
psql -U ? -d ? -h localhost -p 5432 -c "CREATE EXTENSION btree_gist;"
- run:
name: Waiting for MongoDB to be ready
command: |
for i in `seq 1 30`;
do
nc -z localhost 27017 amp;amp; echo Success amp;amp; exit 0
echo -n .
sleep 1
done
echo Failed waiting for MongoDB amp;amp; exit 1
- run:
name: Install npm dependencies
command: |
npm install --save
- run:
name: Run unit tests
command: |
NODE_ENV=test amp;amp; node node_modules/.bin/jest
- run:
name: Run e2e tests
command: |
NODE_ENV=test amp;amp; node node_modules/.bin/jest --runInBand --config ./test/jest-e2e.json --watchAll=false --detectOpenHandles
- store_test_results:
path: test-results
- store_artifacts:
path: test-results
workflows:
build_test:
jobs:
- run_tests
Вероятно, это неэффективно, поскольку таким образом приходится устанавливать клиент psql и зависимости.