Как разбить несколько блоков try catch в powershell

У меня есть класс с +- 25 функциями API, для которого я хочу написать тестовый скрипт.

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

является ли перерыв и вывод моих успехов/ошибок лучшей практикой? или есть лучшие альтернативы для решения этой проблемы?

$API = [API]::NEW()
$SuccessString
$ErrorString

function TestAPIs{

try{
    
    $PersonID = $API.GetPersonByName("test")
    if ($PersonID.id -eq 1)
    {
        $SuccessString += "API function getpersonbyname OK"
    }else
    {
        $ErrorString += "error!!! function returns invalid row!"   
    }

}catch{
       $ErrorString += "critical error: " + $_.Exception.Message
       }


try{
    
    $Permissions = $API.GetPermissions($PersonID)
    if ($Permissions.Records -gt 1)
    {
        $SuccessString += "API function getpermissions OK"
    }else
    {
        $ErrorString += "error!!! permissions returns invalid row!"   
    }

}catch{
       $ErrorString += "critical error: " + $_.Exception.Message
   write-host $SuccessString
   write-host $ErrorString
   BREAK
       }
}

похоже, вы ищете pester: pester.dev

Santiago Squarzon 16.07.2024 19:10

к сожалению, я не могу использовать сторонние модули

user3127554 16.07.2024 19:12

Итак, вопрос в том, как вы можете досрочно выйти из тестовой функции, если один тест не пройден? если да, то вы можете $PSCmdlet.ThrowTerminatingError или просто throw в своем catch блоке

Santiago Squarzon 16.07.2024 19:18

Учитывая ваш пример кода, если вы хотите прекратить выполнение дополнительных тестов из одного из блоков catch, вы можете просто return из своей функции — это вернет управление обратно вызывающему коду. Вы также можете вернуть значение, если вызывающему коду необходимо знать, провалились ли какие-либо тесты, или более сложную структуру, если вы хотите передать более подробные результаты тестов (как, вы знаете, Pester делает :-)).

mclayton 16.07.2024 19:18

Фактически, каждый тест может просто использовать write-output для отправки одного результата теста «пройден» или «не пройден» в виде pscustomobject в выходной поток функции и использовать return для выхода в случае сбоя теста — вызывающий код может получить результаты теста и отображать их так, как он хочет (консоль, запись на диск, выдача в случае сбоя и т. д.). Это отделяет выполнение отдыха от обработки результатов.

mclayton 16.07.2024 19:33

@user3127554 Windows 10/2016 и более поздние версии поставляются с Pester 3.4.0.

Mathias R. Jessen 16.07.2024 21:08
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
70
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Если я правильно понимаю вопрос, вы можете использовать Cmdlet.ThrowTerminationError для создания исключения завершения конвейера, то есть функция завершается, как только возникает критическая ошибка.

function TestAPIs {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [API] $APIObject
    )

    try {
        $PersonID = $APIObject.GetPersonByName('test')
        if ($PersonID.id -eq 1) {
            Write-Host 'API function getpersonbyname OK' -ForegroundColor Green
        }
        else {
            # you can use `$PSCmdlet.WriteError(...)` here
            # if you want to customize your ErrorRecord object
            # by default, if `$ErrorActionPreference` is `Continue`
            # both options will output an error but do not stop the function
            Write-Error 'error!!! function returns invalid row!'
        }
    }
    catch {
        Write-Error 'Critical Error Ocurred'
        $PSCmdlet.ThrowTerminatingError($_) # <= This stops immidiately the pipeline
    }

    try {
        $Permissions = $APIObject.GetPermissions($PersonID)
        if ($Permissions.Records -gt 1) {
            Write-Host 'API function getpermissions OK' -ForegroundColor Green
        }
        else {
            Write-Error 'error!!! permissions returns invalid row!'
        }
    }
    catch {
        Write-Error 'Critical Error Ocurred'
        $PSCmdlet.ThrowTerminatingError($_)
    }
}

$API = [API]::new()
TestAPIs -APIObject $API
Ответ принят как подходящий

Если вы не можете использовать Pester, вы можете, по крайней мере, выбрать некоторые концепции и сделать (очень) базовую версию (настолько простую, что почти стыдно быть уличенным в сравнении ее с Pester :-).

Ключевые части:

  • возвращение структурированных pscustomobject объектов результата вместо записи в консоль — вызывающий код может решить, что делать с результатами

  • досрочный выход из функции тестирования с помощью return, если конкретный неудачный тест означает, что запуск теста должен быть завершен

function TestAPIs {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        $APIObject
    )

    $testName = "GetPersonByName"
    try {
        $PersonID = $API.GetPersonByName("test")
        if ($PersonID.id -eq 1) {
            [pscustomobject] @{
                "Name"        = $testName
                "Success"     = $true
                "Description" = "API function getpersonbyname OK"
            }
        }
        else {
            [pscustomobject] @{
                "Name"        = $testName
                "Success"     = $false
                "Description" = "error!!! function returns invalid row!"
            }
        }
    }
    catch {
        [pscustomobject] @{
            "Name"        = $testName
            "Success"     = $false
            "Description" = "critical error: " + $_.Exception.Message
        }
    }

    $testName = "GetPermissions"
    try {
        $Permissions = $API.GetPermissions($PersonID)
        if ($Permissions.Records -gt 1) {
            [pscustomobject] @{
                "Name"        = $testName
                "Success"     = $true
                "Description" = "API function getpermissions OK"
            }
        }
        else {
            [pscustomobject] @{
                "Name"        = $testName
                "Success"     = $false
                "Description" = "error!!! permissions returns invalid row!"
            }
            # DON'T RUN ANY MORE TESTS IF THIS TEST FAILS
            return
        }
    }
    catch {
        [pscustomobject] @{
            "Name"       = $testName
            "Success"    = $false
            "Description" = "critical error: " + $_.Exception.Message
        }
        # DON'T RUN ANY MORE TESTS IF THIS TEST FAILS
        return
   }

   # ... more tests ...

}

Чтобы использовать его:

$API = [API]::new()

# the foreach-object outputs each individual result to the console
# as they are generated rather then waiting for all results to
# complete before showing anything amd *also* passes the value through
# to $results (so a sort of Tee-Object)
$results = TestAPIs -APIObject $API `
    | foreach-object {
        write-host ($_ | format-list | out-string);
        $_
    }

который выводит это:

Name        : GetPersonByName
Success     : False
Description : critical error: You cannot call a method on a null-valued expression.

Name        : GetPermissions
Success     : False
Description : critical error: You cannot call a method on a null-valued expression.

и заполняет переменную $results, чтобы вы могли делать такие вещи, как:

if ( $results.Success -contains $false )
{
    throw "one or more tests failed"
}

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

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