Лазурный конвейер DevOps | bash-скрипт для запуска теста dotnet в нескольких проектах

Я пытаюсь запустить команду dotnet test для определенных тестовых проектов в конвейере devops MS Azure.

Это работает:

- script: |
    dotnet test "./Project One/Project One Unit Tests.fsproj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
    dotnet test "./Project Two/Project Two Unit Tests.fsproj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
  displayName: 'run tests in cascade'   

Я не хочу указывать имена проектов, только какое-то правило (имя проекта должно заканчиваться на «UnitTests», «Unit Tests» или «Unit_Tests»), но dotnet test <PROJECT> не допускает подстановочных знаков. Похоже, что подстановочные знаки работают с dotnet test <DLL> (./**/*Unit?Tests.dll), но не работают, потому что не находят файл deps.json в папке obj.

Мое решение состоит в том, чтобы пройтись по отфильтрованному списку файлов проекта:

    for proj in ./**/*Unit?Tests.*proj 
    do
      dotnet test "$proj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
    done

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

Я попытался получить результат из прогона, но безуспешно (это не работает):

    for proj in ./**/*Unit?Tests.*proj 
    do
      result=$(dotnet test "$proj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY")
      if result = 1
      then
        exit 1
      fi
    done

Любое предложение? Почему, когда dotnet test терпит неудачу (выход 1), шаг не терпит неудачу? Я попытался ввести в цикл только неудачный тестовый проект, и в этом случае он не работает.

[ОБНОВЛЕНИЕ]
Полный пайплайн.yaml:

trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

variables:
  project file: "Alex75.MySolution/Alex75.MyProject.fsproj"

steps:  

- script: dotnet build -c Release
  displayName: 'Build'
  
- script: |
    dotnet test "./ProjectTwo Unit Tests/ProjectTwo Unit Tests.fsproj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
    dotnet test "./ProjectOne Tests/ProjectOne Unit Tests.fsproj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
  displayName: 'Test'
  condition: false

- script: | 
    for proj in ./**/*Unit?Tests.*proj 
    do
      echo "run tests in $proj"
      dotnet test "$proj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
    done
  displayName: 'Test (Unit Test projects)'
  condition: true

- powershell: |
    $URL = "$(System.CollectionUri)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/logs?api-version=5.1"
    Write-Host "URL = $URL"
  
    $logs = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $(PAT)"} -Method Get 
    $lastLogId = $Logs.value[$Logs.value.count-1].id
    Write-Host "lastLogId = $lastLogId"  
    $URL = "$(System.CollectionUri)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/logs/$lastLogId?api-version=5.1"
    $result = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $(PAT)"} -Method Get 
    Write-Host $result

    Write-Host "Start Check result..."

    $lines = $result.Split([Environment]::NewLine)
    foreach($line in $lines) {
        if ($line -match "Failed!")
        {
            throw 'dotnet test fails ($line)'
        }
    }

    Write-Host "Test result check completed."

  displayName: 'Check tests result'

Сценарий PowerShell

На примере @vito-liu-msft я попытался проверить журналы тестов, чтобы проверить ошибку.

Здесь только скрипт powershell:

$URL = "$(System.CollectionUri)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/logs?api-version=5.1"
Write-Host "URL = $URL"
  
$logs = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $(PAT)"} -Method Get 
$lastLogId = $Logs.value[$Logs.value.count-1].id
Write-Host "lastLogId = $lastLogId"  

$URL = "$(System.CollectionUri)/$(System.TeamProject)/_apis/build/builds/$(Build.BuildId)/logs/$lastLogId?api-version=5.1"
$result = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $(PAT)"} -Method Get 
Write-Host $result

Write-Host "Start Check result..."

$lines = $result.Split([Environment]::NewLine)
foreach($line in $lines) {
    if ($line -match "Failed!")
    {
        throw 'dotnet test fails ($line)'
    }
}

Write-Host "Test result check completed."

PAT — это токен личного доступа, поскольку он создается, его не нужно преобразовывать прежде чем использовать его в HTTP-запросе.
LogId недоступен, поэтому есть запрос на получение коллекции журналов, а затем второй запрос на получение конкретного последнего журнала (ответ кажется упорядоченным по дате, возможно, стоит перепроверить).

Обратите внимание, что если второй запрос вернет 404, 500 или другой результат (не сбой), проверка ошибок не найдет фактических ошибок! Требуется надлежащая проверка ответа.

Я проверил -match "Failed!" в PowerShell, но я не тестировал команду throw в конвейере, потому что...

Команда dotnet test в цикле работает!

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

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

В любом случае это инкриминируемый шаг (сценарий):

    for proj in ./**/*Unit?Tests.*proj 
    do
      echo "run tests in $proj"
      dotnet test "$proj" -c Release --no-build --filter "TestCategory!=SKIP_ON_DEPLOY & TestCategory!=REQUIRES_API_KEY"
    done

В списке с эхом можно увидеть, какие тестовые проекты используются.

Привет! Просто проверяю, блокирует ли тебя эта проблема? Любое обновление для этой проблемы?

Vito Liu 16.12.2020 08:55

Честно говоря, все еще ищу что-нибудь попроще, но обязательно посмотрю через пару дней. Спасибо.

Alex 75 16.12.2020 10:31
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
1 511
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

когда тест проекта терпит неудачу, он не проваливает шаг, поэтому конвейер не останавливается! Почему при сбое теста dotnet (выход 1) шаг не завершается ошибкой?

В качестве обходного пути мы можем получить dotnet test идентификатор журнала задач через этот rest API, добавить задачу power shell и ввести приведенный ниже скрипт для анализа dotnet test журнала. нам нужно ввести код совпадения, например fails (exit 1). Если тест dotnet не пройден, конвейер остановится.

Мы должны добавить PAT в переменную и установить ее в секрет, а затем использовать ее в скрипте.

$connectionToken = "{PAT}"
$base64AuthInfo= [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$($connectionToken)"))
$URL = "https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}/logs/{logId}?api-version=6.1-preview.2"
$Result = Invoke-RestMethod -Uri $URL -Headers @{authorization = "Basic $base64AuthInfo"} -Method Get 
Write-Host $result
$lines = $result.Split([Environment]::NewLine)

        $passed = 0;
        $failed = 0;

        foreach($line in $lines) {
            if ($line -match "{match sentence}") { 
              throw 'dotnet test fails (exit 1)'

            }
        }

Обновление1

как я могу найти "logId"?

Мы могли бы использовать этот REST API для проверки logId

GET https://dev.azure.com/{organization}/{project}/_apis/build/builds/{buildId}/logs?api-version=6.1-preview.2

Результат:

И мне действительно нужно использовать «предварительную» версию API?

Мы также могли бы использовать другую версию, например 5.1, мы могли бы изменить версию REST API в документе, вы можете проверить рисунок ниже.

Я создал токен личного доступа и переменную с именем «PAT» в сборке конвейера. Несмотря на то, что в документации сказано: Пакетный сценарий: %VARIABLE-NAME% PowerShell script: ${env:VARIABLE-NAME} Bash script: $(VARIABLE-NAME) на самом деле, чтобы заставить его работать в сценарии PowerShell, мне пришлось использовать $(VARIABLE NAME ). Хорошо, я создаю URL-адрес: $URL = "$(System.CollectionUri)/$(System.TeamProject)/_apis/build/b‌​uilds/$(Build.BuildN‌​umber)/logs/{logId}?‌​ api-version=6.1-prev‌​iew.2" Предполагая, что «buildId» правильный, как я могу найти «logId»? И мне действительно нужно использовать «предварительную» версию API?

Alex 75 17.12.2020 00:06

Привет @ Alex75, я обновил ответ, пожалуйста, проверьте его.

Vito Liu 17.12.2020 08:53

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

Vito Liu 22.12.2020 10:49

Другие вопросы по теме