Jest: Процесс Jest не завершается после завершения последнего теста

Созданный на 18 авг. 2016  ·  60Комментарии  ·  Источник: facebook/jest

У меня проблемы с тем, что процесс Jest не завершается после завершения последнего теста. Пользователь должен будет принудительно завершить процесс с помощью ctrl-c. Моя теория состоит в том, что не все ресурсы должным образом очищаются авторами тестов, но в идеале Jest все равно должен выйти.

В частности, я тестирую Firebase с помощью firebase-server , увеличивая один или несколько серверов для каждого теста. В действии afterEach мы вызываем метод close для всех серверов, созданных в последнем тесте, однако даже с этим методом процесс Jest все равно не завершается.

Есть ли способ заставить процесс Jest завершиться после завершения тестов (пройден или не пройден)? Есть ли способ получить хук afterAll для очистки всех оставшихся ресурсов? Есть ли способ отладить, что именно удерживает процесс Jest от завершения? Благодарю.

Enhancement Help Wanted good first issue

Самый полезный комментарий

для всех, кто читает, вы можете использовать флаг --forceExit для доступа к этой функции. 🎉

Все 60 Комментарий

У нас сейчас нет хорошего способа сделать это. Я бы рекомендовал попробовать подключиться к отладчику (Chrome Inspector), чтобы выяснить, что происходит. Если вы знаете, что создает асинхронную работу, вы также можете исправить ее и отслеживать (например, поместить что-то вокруг Promise.prototype.then)

Есть ли причина, по которой асинхронная работа не может быть принудительно завершена, когда все хуки afterEach / after разрешены?

Я не знаю, как бы вы уничтожили существующие асинхронные процессы, если бы не управляли ими.

Я перешел с ava и это не было проблемой, так что, может быть, есть ответ? Может быть, это process.exit в Node.js

Я думаю, мы могли бы это сделать, но меня беспокоит, что это заставит людей не зависать, когда нужно, и они не отключают свои ресурсы должным образом.

cc @dmitriiabramov что ты думаешь?

Один пример: я сам столкнулся с этим с Jest, где у нас был длительный процесс-наблюдатель, который не завершал сам Jest. Если бы Jest убил себя во время тестового запуска (хех!), Я бы никогда не заметил эту проблему и отправил бы версию, которая зависает, когда люди пытаются ее использовать.

Я не уверен, безопасно ли принудительно убить процесс. в то же время, если люди хотят выполнить некоторую асинхронную пост-обработку после завершения тестов, они могут использовать after all хук, который будет ждать его завершения перед выходом из процесса.

другая проблема, которая может возникнуть, - это обрезать выходной поток до того, как он завершит печать. у нас была эта проблема раньше, когда сообщения об ошибках не успевали распечатать до завершения процесса.

Вопрос в том, сможем ли мы придумать способ, которым Jest скажет: «Похоже, некоторые тесты не убираются за собой. Вот что происходит».

Здесь мне может помочь хук after all , но я не видел ничего подобного в документации (только afterEach ). Я что-то упускаю?

Что касается проверки правильности очистки, если вы можете проверить, завершаются ли _файлы_ вовремя и не используют ли они функцию пополам для изоляции проблемы (как в rspec).

Хорошо, поэтому после дополнительных исследований это, похоже, проблема с самой Firebase, и нет никакого способа очистить, кроме вызова process.exit .

Ресурсы:

Все обходные пути включают ручной вызов process.exit . Боюсь делать это в контексте шутки, есть ли рекомендация, куда поставить такой вызов? Моя первая мысль была примерно такой:

afterAll(() => setTimeout(() => process.exit(), 1000))

… Чтобы выйти через одну секунду после завершения всех тестов, чтобы позволить Jest сделать свое дело, однако я не уверен, как это влияет на режим просмотра, и, если я прав, Jest делает некоторые причудливые вещи параллелизма, которые могут сделать это не так, как ожидалось. В качестве альтернативы, нужно ли это исправить в самом Jest? Если многим это покажется пистолетом, почему бы не добавить его в Jest? Или, по крайней мере, переключение между режимами «предупреждения» и «уничтожения».

Мне бы понравился флаг --exit или что-то в этом роде (это может быть комментарий к файлу или что-то в этом роде), который автоматически закрывает процессы после завершения тестов, аналогично мокко. немного раздражает вручную закрывать каждое соединение в каждом тестовом файле.

У меня такая же проблема, когда я запускаю тесты в Codeship . Он также не работает на drone.io .
Хотя локально он работает нормально.

РЕДАКТИРОВАТЬ:

  • Версия Jest : 15.1.1
  • Местный :

    • Узел: 6.2.2

    • npm: 3,9,5

  • CodeShip :

    • Узел: 6.5.0

    • npm: 3.10.3

  • Drone.io

    • Узел: 0.10.26

    • npm: 1.4.3

Мне кажется, что Firebase надо исправить.

У меня нет никаких оговорок против добавления опции под названием --forceExitAfterTestRun и ее должно быть легко добавить. Я думаю, что для выхода здесь просто требуется изменение: https://github.com/facebook/jest/blob/master/packages/jest-cli/src/cli/index.js#L41, если флаг установлен независимо от результат.

Похоже, это своего рода состояние гонки. Иногда он завершается после выполнения всех тестов локально, иногда нет ...

Я запускаю это также после того, как начал использовать Jest для своих спецификаций API, где я использую настоящую базу данных вместо имитаций (извините, но снимки отлично подходят для этого). Я все же смог решить проблему даже после добавления хуков afterAll для очистки соединений, что наводит меня на мысль, что это каким-то образом связано с моим набором приборов в setupFiles , а не самым простым для отладки.

У Жасмин, похоже, есть опция --forceexit поэтому я бы не стал жаловаться, если подобное также попадет в Jest 🙏

другая проблема - если тест не проходит, то afterAll() не вызывается, поэтому ничего не очищается и ничего не закрывается. я думаю, что --bail исправит это, но я еще не пробовал

Если кто-то хочет отправить PR, это то, с чем мы могли бы помочь, и я изложил детали в своем предыдущем комментарии :)

Я попробую, если у меня будет немного времени на выходных. Если кто-то захочет сделать это раньше, было бы здорово: smile:

Закрытие в пользу только что открытого PR. Мы продолжим обсуждение там.

для всех, кто читает, вы можете использовать флаг --forceExit для доступа к этой функции. 🎉

Для гуглеров: Jest не завершается на Jenkins CI, в то время как он работает локально .. --forceExit действительно исправил это для меня.

Для меня это было забыть об обработке обещаний с помощью .then (() => {}) - выполнил свою работу

Я все еще борюсь с этим. Я тестирую API с async и await . Я подключаюсь к своему экспресс-приложению и проверяю связь с конечной точкой, но тест не завершается. Я пытался закрыть соединение с mongodb и сервером, но он все еще открыт. Я отправляю только пустой json.

В моем случае это оказалось проблемой Firebase. С помощью

afterAll(() => {
  firebaseApp.database().goOffline();
  firebaseApp.delete();
});

кажется, делает свое дело. Я обнаружил, что обе строки действительно необходимы и вам нужно использовать тот же firebaseApp который вы изначально получаете из .initializeApp() .

Есть ли способ решить эту проблему без forceExit?

Jest 23 включает флаг под названием --detectOpenHandles который должен указывать на источник, почему Jest не может выйти.

--detectOpenHandles возвращает mongoose.connect и mongoose.model. Попытка mongoose.disconnect в afterAll вызывает ошибку mongo. Топология уничтожена.

screenshot 2018-06-08 11 14 51
screenshot 2018-06-08 11 14 29

@elkhan ты понял , как решить проблемы мангуста?

После добавления --detectOpenHandles Jest не только завершает мои тесты, но и не показывает ничего, что на самом деле блокирует Jest, что странно. Похоже на ошибку.

Для меня --forceExit решает проблему, в то же время я использую --detectOpenHandles но он ничего не обнаруживает (как локально, так и на CircleCI). Я тоже бегаю с --runInBand .

Для меня удаление --runInBand решило эту проблему.

--forceExit решает проблему и для меня при использовании shippable ... Пробовал --detectOpenHandles но не дал никаких результатов и все равно просто зависание сборки

Добавление --detectOpenHandles устраняет причудливую проблему.

Узел: v8.12.0
Шутка: v23.6.0

Добавление --detectOpenHandles или --forceExit не решает для меня проблему при работе в Codeship.

jest --ci --verbose --forceExit --detectOpenHandle

Узел: v8.12.0
Шутка: v23.6.0

@sibelius способ избежать этой проблемы -

const mongoose = require('mongoose');

mongoose.Model.init = () => {};

Это не позволит Jest жаловаться на модели, хотя индексы не будут созданы.

db.collection("test-collection").add({
    title: 'post title',
    content: 'This is the test post content.',
    date: new Date(),
})
    .then(docRef => {
        console.log('Document written with ID: ', docRef);
    })
    .catch(error => {
        console.error('Error adding document: ', error);
    });

jest --forceExit --detectOpenHandle тесты пройдены, но код в .then или .catch не запускается !!
есть идеи?

@alexpchin Вот как я это решил:

    beforeAll(async (done) => {
        dbConnection = await mongoose.connect(...)
        done()
    })

    afterAll(async (done) => {
        await dbConnection.close()
        dbConnection.on('disconnected', done)
    })

С NestJs мне пришлось добавить

afterAll(() => {
  app.close();
});

Мы обнаружили, что эта проблема была вызвана нехваткой памяти в процессе шутки. Добавление --maxWorkers=10 устранило проблему для нас.

Я добавляю эту причину, возможно, у кого-то, интересующегося этой проблемой, может быть причина, как и у меня.
Я использовал Jest в Travis для тестирования приложения NodeJS, и Travis зависал до тайм-аута сразу после Jest. Похоже, Jest не закрывался.
После многих попыток я обнаружил, что причина в использовании шутки с JSDom.
В моем файле jest.config.js была следующая строка:

  'testURL': 'http://localhost/',

Это привело к загрузке JSDom и, предположительно, не закрытию всех ресурсов изящно и сохранению Jest в живых.

Я решил это, удалив строку, однако затем Jest выйдет из строя со следующей ошибкой, см. Это :

SecurityError: localStorage is not available for opaque origins

Чтобы решить эту проблему, я добавил в jest.config.js :

  'testEnvironment': 'node',

Надеюсь, это поможет кому-нибудь. Я добавляю эту причину, возможно, у кого-то, интересующегося этой проблемой, может быть причина, как и у меня.
Я использовал Jest в Travis для тестирования приложения NodeJS, и Travis зависал до тайм-аута сразу после Jest. Похоже, Jest не закрывался.
После многих попыток я обнаружил, что причина в использовании шутки с JSDom.
В моем файле jest.config.js была следующая строка:

  'testURL': 'http://localhost/',

Это привело к загрузке JSDom и, предположительно, не закрытию всех ресурсов изящно и сохранению Jest в живых.

Я решил это, удалив строку, однако затем Jest выйдет из строя со следующей ошибкой, см. Это :

SecurityError: localStorage is not available for opaque origins

Чтобы решить эту проблему, я добавил в jest.config.js :

  'testEnvironment': 'node',

Надеюсь, это кому-нибудь поможет.

--forceExit --detectOpenHandles --maxWorkers = 10

сделал это для нас

узел: 8.11.3
шутка 23.6.0

С NestJs мне пришлось добавить

afterAll(() => {
  app.close();
});

Просто оставьте это здесь для людей NestJS:
С NestJS я обнаружил, что приведенный выше ответ действительно работает.
НЕ РАБОТАЕТ следующее:

afterAll(async () => {
        await app.close()
    })

для меня работает --forceExit --maxWorkers=10 (я использую Ubuntu 18.04, использую [email protected])

В моем случае использование NodeJS 10 или 11 устраняет проблему, но она все еще существует с Node 6 или Node 8. при использовании параметра --detectOpenHandles ничего не отображается, и --forceExit устраняет проблему.

Еще +1 человек здесь (например, @motss и @seanlindo ), наблюдающий, что _ "Jest не завершился через одну секунду после завершения тестового запуска". _ Появляется только тогда, когда --detectOpenHandles не используется.

[email protected]

Тесты постоянно терпят неудачу без --detectOpenHandles но проходят и не показывают никаких открытых дескрипторов при запуске с --detectOpenHandles .

Машина / контейнер, на котором выполняются тесты, имеет два ядра, но по умолчанию тесты выполняются с maxWorkers=1

Когда я добавляю флаг --detectOpenHandles и смотрю на config / globalConfig, используя флаг --debug , значение detectOpenHandles - это _only_ разница ...

Если я запустил with --runInBand --detectOpenHandles тесты все равно пройдут нормально.

Я могу выполнить любое из следующих действий, чтобы успешно завершить тесты без отображения ошибки «... не завершился ...»:

  • jest --maxWorkers=2
  • jest --detectOpenHandles
  • jest --forceExit

Пока работаю с maxWorkers=2 , но это мои наблюдения, просто для тех, кто ищет в будущем ...

_Edit: Дополнительная деталь: это влияет только на мою среду CI, которая является контейнером докеров FROM alpine: 3.7 running node v8.9.3. Я не могу воспроизвести с помощью --maxWorkers=1 на моей машине разработчика_

Подтверждаю, я получаю эту ошибку прямо сейчас. Использование --maxWorkers=10 похоже, решает проблему.

Итак .... Я боролся с этим довольно долгое время (используя travis ci, комбинезон и машинопись).
В конечном итоге он зависнет и произведет неудачную сборку (но только с Travis CI).

После долгих проб и ошибок я обнаружил, что для меня это исправило то, что я добавил явный путь к тестам.

Не удалось выполнить сценарий npm

   "test": "jest",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

И прошел (в travis ci) с:

   "test": "jest .*\.test\.ts",
    "test:coverage": "npm run test -- --collectCoverage && cat ./src/coverage/lcov.info | coveralls",

Если вы используете докер с изображением Redhat UBI и create-react-app убедитесь, что вы установили CI=true перед запуском npm test

Декабрь 2019. Пробирался ТОЛЬКО по Трэвису. Тесты проходят локально. Исправление @qopqopqop сработало для меня. Использование Jest версии 24.9.0

Я столкнулся с этой ошибкой только тогда, когда в наш проект начали добавлять новые компоненты, использующие хуки и библиотеку тестирования. Я думаю, что между хуками Jest, testing-library и React могут быть некоторые трения, поскольку все это новые технологии. Эти проекты все еще учатся хорошо играть друг с другом. ИЛИ, мы можем писать действительно ошибочные функциональные компоненты, которые неправильно используют хуки. :-)

У меня все еще есть эта проблема. Я не могу выйти из теста, это приведет к сбою npm test для всего моего приложения. любая подсказка?

@koooge Можете ли вы опубликовать пример того, что вам не подходит?

Чтобы выполнить тестовый выход с 0 после того, как все тесты пройдут, вам необходимо пройти --watchAll = false
как npm run test - --watchAll = false

это сработало для меня

Чтобы это работало с Firebase, мне пришлось сделать следующее:

afterAll(() => {
    firebase.app().delete();
});

Я исправил это с помощью опции:

--forceExit

https://jestjs.io/docs/en/cli# --forceexit

Так что я тоже столкнулся с этой проблемой. Было неприятно видеть предупреждающее сообщение A worker process has failed to exit gracefully and has been force exited... когда я знал, что обрабатываю все свои вызовы async правильно. Я провел свои тесты с --detectOpenHandles но ничего не обнаружил. После некоторого исследования я обнаружил, что моим виновником был Promise.race .

Я использую встроенную библиотеку служебных программ обещаний (https://github.com/blend/promise-utils) и оборачиваю некоторые из моих внешних вызовов API в служебную программу timeout . Эта утилита, в свою очередь, использует собственный Promise.race .

Я вытащил этот код и создал простой тестовый пример, чтобы подтвердить свои выводы.

it('promise.race', async() => {
  await Promise.race([
    new Promise((res) => setTimeout(res, 10000)),
    Promise.resolve('true')
  ])
})

Предполагая, что настройки тайм-аута вашего тестового примера заданы по умолчанию, вышеуказанный тест всегда будет выдавать предупреждение.

Независимо от того, каким способом jest обнаруживает открытые дескрипторы под капотом, он не принимает во внимание дескрипторы, оставленные открытыми намеренно Promise.race . Этот вариант использования определенно попадает в категорию ложных срабатываний. Я не уверен, что это ложное срабатывание можно исправить, но, возможно, у одного из разработчиков есть гениальное решение этой проблемы.

На данный момент я придерживаюсь --forceExit как и все остальные.

Редактировать:
Только что нашел это, похоже, что это действительно более глубокая проблема nodejs / v8 https://github.com/nodejs/node/issues/24321

Для всех, кто пришел сюда из тестов Firestore, это работает для меня:

afterAll(async () => {
  // Shut down Firestore, otherwise jest doesn't exit cleanly
  await firestoreInstance.terminate()
});

У меня все еще та же проблема с Apollo & Jest. К сожалению, даже несмотря на то, что опция --detectOpenHandles конечном итоге завершается, она по-прежнему приостанавливает процесс еще на несколько секунд (и вопреки своему названию: он не предоставляет информацию о том, какие дескрипторы все еще открыты!).

Использование --forceExit выполняет свою работу, но неприятно печатает:

Принудительный выход из Jest: рассматривали ли вы возможность использования --detectOpenHandles для обнаружения асинхронных операций, которые продолжали выполняться после> завершения всех тестов?

Я нашел обходной путь (и это ни в коем случае не решение!) - добавить teardown в jest.config.js:

globalTeardown: '<rootDir>/__tests__/teardown.js',

а в teardown.js используйте process.exit:

module.exports = async function () {
    console.log('done!');
    process.exit(0);
}

У меня тоже такая проблема. Как я могу это исправить? Я установил forceExit: true . --forceExit --detectOpenHandles --maxWorkers=10 не работает.

https://github.com/atom-ide-community/atom-ide-base/pull/33

Изменить: проблема в другом месте. Я использую тест-раннер ...

@alusicode
У меня не получилось npm test --watchAll=false
Но это сработало, добавив --watchAll=false в файл package.json. 👍

подобно

"test": "react-scripts test a jest --ci --reporters=default --reporters=jest-junit --watchAll=false"

Официальные документы: https://jestjs.io/docs/en/cli.html# --watchall

Я не использую firebase, но у меня была такая же проблема с моими сценариями рабочего процесса. использование jest без параметров говорит о том, что некоторые из моих скриптов не завершились корректно, и я должен использовать --runInBand --detectOpenHandles . Это решило бы проблему для всех моих тестов, кроме одного (кстати, --detectOpenHandles не показал мне тесты, в которых были проблемы).
Я начал проверять все тесты один за другим. Я обнаружил, что для двух тестов я забыл использовать await при вызове асинхронной функции.
После добавления await это было исправлено. Хотя я не думаю, что это нормально, что --detectOpenHandles не печатает проблемы.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги