У меня есть класс с +- 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
}
}
к сожалению, я не могу использовать сторонние модули
Итак, вопрос в том, как вы можете досрочно выйти из тестовой функции, если один тест не пройден? если да, то вы можете $PSCmdlet.ThrowTerminatingError
или просто throw
в своем catch
блоке
Учитывая ваш пример кода, если вы хотите прекратить выполнение дополнительных тестов из одного из блоков catch
, вы можете просто return
из своей функции — это вернет управление обратно вызывающему коду. Вы также можете вернуть значение, если вызывающему коду необходимо знать, провалились ли какие-либо тесты, или более сложную структуру, если вы хотите передать более подробные результаты тестов (как, вы знаете, Pester делает :-)).
Фактически, каждый тест может просто использовать write-output
для отправки одного результата теста «пройден» или «не пройден» в виде pscustomobject в выходной поток функции и использовать return
для выхода в случае сбоя теста — вызывающий код может получить результаты теста и отображать их так, как он хочет (консоль, запись на диск, выдача в случае сбоя и т. д.). Это отделяет выполнение отдыха от обработки результатов.
@user3127554 Windows 10/2016 и более поздние версии поставляются с Pester 3.4.0.
Если я правильно понимаю вопрос, вы можете использовать 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, вам следует это сделать, но если вы не можете, то приведенное выше может дать небольшой шаг вперед по сравнению с тем, где уже был ваш код...
похоже, вы ищете pester: pester.dev