Проблемы с синхронизацией GI - PullRequest
0 голосов
/ 11 мая 2018

Используя CI Gitlab для автоматического запуска модульных тестов, я столкнулся с проблемой, когда конкретный контрольный пример будет иногда терпеть неудачу только на gitlab-runner и никогда в моей среде разработки. Когда что-то не работает детерминистически, я волнуюсь и хочу докопаться до сути.

Вот тестовый пример, обратите внимание, что время имеет решающее значение:

def test_get_file_url(self):
    # 1. get pre-signed URL to file
    expiration = 3
    url = s3.get_file_url(file_default.key, expires=expiration)

    # 2. download file contents, make sure contents match expectation
    response = requests.get(url)
    content = response.content
    self.assertEqual(content, file_default.bytes)

    # 3. sleep long enough for URL to expire
    time_to_sleep = expiration * 4
    start_time = time.time()
    time.sleep(time_to_sleep)
    end_time = time.time()
    time_slept = end_time - start_time
    print("time slept: {} seconds, expected: {} seconds".format(time_slept, time_to_sleep))

    # 4. make request, expecting URL to have expired
    response2 = requests.get(url)
    content2 = response2.content
    self.assertIn("Request has expired", str(content2))    # THIS FAILS (sometimes)

Некоторое объяснение:

  1. s3.get_file_url(...) возвращает предварительно подписанный URL-адрес для файла на AWS S3, срок действия которого истекает через указанные 3 секунды. Учетные данные AWS и имя сегмента S3 предоставляются в методе / s3-модуле.
  2. Загрузите файл по этому URL и убедитесь, что файл содержит то, что он должен содержать.
  3. Спит достаточно долго (намного дольше, чем необходимо), чтобы срок действия URL истек.
  4. Сделайте запрос на тот же URL, ожидая, что срок действия URL истек. Здесь тестовый случай иногда завершается неудачей. Я ожидаю, что XML-содержимое содержит строку «Запрос истек», но вместо этого я по-прежнему получаю фактическое содержимое файла.

Для ясности: при сбое конвейера я нажимаю кнопку повтора в веб-интерфейсе gitlab, и он может работать - никакого кода не изменилось!

Что я сделал:

  1. увеличить time_to_sleep = expiration * 10 безрезультатно
  2. измерение фактического time_slept, как видно из кода выше (вывод подтверждает 12+ секунд)

.gitlab-ci.yml:

image: "python:3.6.4"

before_script:
  - pip3 install pipenv
  - pipenv install --dev

test:
  script:
  - TESTING=True pipenv run coverage run --source=myapp -m unittest discover -s myapp
  - pipenv run coverage report | grep TOTAL
  tags:
  - unittesting

Некоторые (очень сомнительные) предположения:

  1. пакет requests каким-то образом возвращает кэшированный ответ на тот же URL
    • как бы это отключить?
    • почему это не всегда происходит?
  2. 2-й requests.get(url) фактически каким-то образом выполняется до того, как time.sleep(time_to_sleep) возвращает:
    • может time.sleep() как-то быть неблокирующим?
    • мои измерения не работают должным образом

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

...