Veriye Dayalı Pester ile PowerShell Test Ustalığı
Pester'ı uzun süredir ara ara kullanıyorum. PowerShell kodumda güvenilirliği sağlama konusunda her zaman takıntılı oldum. Pester Kitabı'nı yazdıktan ve bu blog yazısında Pester v4 ile kullandığım bazı metodolojilerden bahsettikten sonra Pester v5'in işimi çok kolaylaştırdığını öğrendim.
Görüyorsunuz, Pester ile testler oluşturduğunuzda seçenekleriniz PowerShell'deki her şey gibi sınırsızdır. Testleri milyonlarca farklı şekilde yapılandırabilirsiniz çünkü testlerin içine istediğiniz PowerShell'i yazmakta özgürsünüz. Ancak bu her zaman iyi bir şey değildir. Bunları oluşturmak için bir tür metodolojiye veya genel yola ihtiyacınız var. Bu benim tercih ettiğim yoldur; veriye dayalı testler.
Veriye Dayalı Testler Nelerdir?
Tipik bir Pester test paketinde, yapmanız gereken her iddia için genellikle bir it bloğu oluşturursunuz. Aşağıdakileri yapmak için bir it bloğu oluşturursunuz:
- betiğin doğru çıktıyı döndürdüğünü iddia edin
- betiğin doğru bir işlevi çağırdığını iddia edin
- betiğin doğru konumda bir dosya oluşturduğunu iddia edin.
- …İmkanlar sonsuzdur
Bu senaryoların her biri için, bir adla bir it bloğu oluşturursunuz ve test ettiğiniz eylemi gerçekleştirmek için komut dosyasına aktarılacak tüm parametreleri sağlarsınız.
Örneğin:
describe 'some script' {
it 'creates a thing given the parameters to do so' {
./thing.ps1 -Create -Name 'xxx' | should -BeTrue
}
it 'sets a thing given the parameters to do so' {
./thing.ps1 -Set -Name 'xxx' | should -BeTrue
}
it 'removes a thing given the parameters to do so' {
./thing.ps1 -Remove -Name 'xxx' | should -BeTrue
}
}
Haklısın. Gerekli parametreleri sağlayarak her senaryoyu tanımladınız ve betiğin true değerini döndürdüğünü iddia ettiniz. Bu, testler oluşturmanın yaygın bir yoludur ancak bu yaklaşım beni her zaman rahatsız etmiştir. Bir dizide bir şeyler saklayabildiğimde gereksiz yere kodu kopyalıyormuşum gibi hissettim.
Görünüşe göre yapabilirim!
Pester v5'te, parametre kümelerinin tümünü aynı anda bloklara aktaran ve Pester'ın her parametre kümesi için testi yürütmesini sağlayan foreach döngüsünün bir parçası olan testler oluşturabilirsiniz.
Yukarıdaki örnekte aynı komut dosyası için üç farklı parametre seti kullanıyorsunuz. Bu kümeler bir karma tablo dizisinde tanımlanabilir.
$paramSets = @(
@{
Create = $true
Name = 'xxx'
}
{
Set = $true
Name = 'xxx'
}
{
Remove = $true
Name = 'xxx'
}
)Bunların tümü bu dizide depolandıktan sonra Pester v5'in foreach özelliğini kullanarak bunları it bloğu gibi bir bloğa "bağlayabilirsiniz".
it 'whatever test name here' -ForEach $paramSets {
## The parameter set is now represented as the current iteraction in the foreach loop
$paramSet = $_
& "./thing.ps1" @paramSet | should -BeTrue
}Pester testini şimdi çalıştırdığınızda, dizideki her parametre setini it bloğuna geçirecek ve yalnızca tek bir it bloğu tanımlayarak üç test gerçekleştirecektir! Çok daha verimli.
PowerShell Test Kodunu KURU Tutmak
Her yazılım geliştiricisi DRY yöntemi kavramını bilir. Özetle, kendinizi tekrar etmemek. Bu, mümkün olduğunca kodun kopyalanmaması anlamına gelir. Neden? Sürdürülebilirlik için.
100 veritabanı kaydı oluşturmanız gerektiğini ve aşağıdaki gibi bir kod gördüğünüzü düşünün:
New-Record -Table 'xxxx' -Fields @{ name = 'whatever1' }
New-Record -Table 'xxxx' -Fields @{ name = ' whatever2' }
New-Record -Table 'xxxx' -Fields @{ name = ' whatever3' }
New-Record -Table 'xxxx' -Fields @{ name = ' whatever4' }
New-Record -Table 'xxxx' -Fields @{ name = ' whatever5' }
New-Record -Table 'xxxx' -Fields @{ name = ' whatever6' }
## to 100Bu, kodu basitleştirmek ve bakımı çok daha kolay hale getirmek için kolayca dörde indirilebilen 100 satırlık koddur.
$whateverCount = 100
for ($i = 1; $i -lt $whateverCount; $i++) {
New-Record -Table 'xxxx' -Fields @{ name = "whatever$i" }
}Yalnızca kodu basitleştirmekle kalmadı, aynı zamanda yalnızca bir sayıyı değiştirerek bir milyon kayıt oluşturabilirsiniz. Bu KURU.
O halde neden bazı insanlar Pester testlerini böyle yazıyor?
describe 'some script' {
it 'creates a thing given the parameters to do so' {
./thing.ps1 -Create -Name 'xxx'
}
it 'sets a thing given the parameters to do so' {
./thing.ps1 -Set -Name 'xxx'
}
it 'removes a thing given the parameters to do so' {
./thing.ps1 -Remove -Name 'xxx'
}
}Test etme konusunda yeniyseniz veya Pester'ın belgelerini gerçekten okuyorsanız, örneklerin çoğunun bu şekilde yapılandırılmış olduğunu göreceksiniz. Ve bunda kesinlikle yanlış bir şey yok! Basit komut dosyaları için küçük bir avuç test oluşturuyorsanız, gayet iyi çalışıyor. Ama bu beni her zaman rahatsız etti.
O kadar açık olmasa da aslında aynı şeyi yapıyorsunuz; çoğaltma işlevi. Ancak Pester testlerini DRY yapmak, bir for döngüsü eklemek ve tek bir değişken eklemek kadar basit değildir. Bunları Pester'ın alana özgü dilini (DSL) kullanacak şekilde yapılandırmanız gerekir.
Daha İyi Test Kapsamı
PowerShell kodu gibi testler yazmak gerçekten bir sanattır. Aynı eylemi gerçekleştirmenin her birinin yararları ve sakıncaları olan birçok yolu vardır. Büyük PowerShell betikleri için testler yazarken çıldırabilir ve her…küçük…dakikayı…ayrıntıyı test edebilirsiniz. Veya çevik rotaya gidebilir ve çoğu durumu kapsayan küçük bir test seti oluşturabilir ve betiğin vahşi ortamda kullanıldığında nasıl başarısız olduğunu keşfettikçe testler ekleyebilirsiniz.
İkisi arasında nasıl bir uzlaşma sağlarsınız? Veriye dayalı testler!
Veriye dayalı testlerle, bir dizide mümkün olan her parametre kümesini önceden tanımlayarak komut dosyanızın çağrılabileceği her, tek yolu tanımlayabilirsiniz.
Pester'ın Veriye Dayalı Testleri Nasıl Yapılır?
Artık veri odaklı testlere aşina olduğunuza göre, PowerShell kodum için yönetilebilir test kapsamı sağlamak amacıyla kişisel olarak kullandığım yöntemi ele alalım.
Zorunlu parametreleri bir karma tablosunda tanımlayın.
$mandatoryParameters = @{ EndpointApiKey = (ConvertTo-SecureString -String 'apikeyhere' -AsPlainText -Force) PasswordName = 'namehere' NewPassword = (ConvertTo-SecureString -String 'passwordhere' -AsPlainText -Force) }Zorunlu parametreleriniz varsa bunları her çalıştırmada komut dosyasına aktarmanız gerekeceğini bilirsiniz, bu nedenle önce bunları tanımlayın.
Hem parametre seti karma tablosunu hem de test adını içeren bir karma tablosu dizisi oluşturun.
$mandatoryParameters = @{ EndpointApiKey = (ConvertTo-SecureString -String 'apikeyhere' -AsPlainText -Force) PasswordName = 'namehere' NewPassword = (ConvertTo-SecureString -String 'passwordhere' -AsPlainText -Force) } $parameterSets = @( @{ label = 'all mandatory parameters' parameter_set = $mandatoryParameters } @{ label = 'specific EndpointUri' parameter_set = $mandatoryParameters + @{ 'EndpointUri' = 'https://endpointhere' } } )Zorunlu parametreleri kopyalamak yerine
parameter_setanahtarındaki parametre kümesine daha fazla parametre eklediğime dikkat edin.Tüm durumlara uygulanacak ana
bağlambloğunu oluşturun.context 'Global' { ## do whatever in here that depends on the script }Her çevresel durum için bir
contextbloğu oluşturun.context 'when the file exists' { } context 'when the file does not exist' { }Her bağlama iletilen parametre kümelerini önceden filtreleyerek sınırlayın.
context 'when the file exists' { $ctxParameterSets = $parameterSets.where({ $_.parameter_set.ContainsKey('EndpointUri'') }) }Yapmanız gereken testleri temsil eden
itblokları oluşturun.it 'passes the expected URI to the API to update the password : <_.label>' -ForEach $parameterSets { & "$PSScriptRootthing.ps1" @parameter_set | should.... }Pester v5'te test adının içine bir dize ekleyebilirsiniz. Bu parametre kümesinin ne olduğuna ilişkin bir açıklama eklemek için ilk olarak label adı verilen diziden bir anahtar kullanıyorum.
Tüm testleri bu şekilde oluşturduktan sonra, ihtiyacım olan tüm testleri otomatik olarak çalıştıracak parametre setlerini diziye kolayca ekleyebilirim!