время ожидания nestjs истекает через 10 минут circleci

#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 и зависимости.