Latihan - Menambahkan pengujian unit ke aplikasi Anda
Di unit ini, kita akan menambahkan pengujian unit ke build otomatis yang kita buat dengan Microsoft Azure Pipelines. Bug regresi merayap ke dalam kode tim Anda dan merusak fungsionalitas pemfilteran papan peringkat. Secara khusus, mode permainan yang salah terus muncul.
Gambar berikut mengilustrasikan masalahnya. Ketika pengguna memilih "Bima Sakti" untuk hanya menampilkan skor dari peta permainan itu, mereka mendapatkan hasil dari peta game lain, seperti Andromeda.
Tim ingin menangkap kesalahan sebelum mencapai penguji. Pengujian unit adalah cara yang bagus untuk secara otomatis menguji bug regresi.
Menambahkan pengujian unit pada saat ini dalam proses akan memberi tim awal saat mereka meningkatkan aplikasi web Space Game . Aplikasi ini menggunakan database dokumen untuk menyimpan skor tinggi dan profil pemutar. Saat ini, ia menggunakan data pengujian lokal. Kemudian, mereka berencana untuk menyambungkan aplikasi ke database langsung.
Banyak kerangka kerja pengujian unit tersedia untuk aplikasi C#. Kami akan menggunakan NUnit karena populer dengan komunitas.
Berikut adalah pengujian unit yang sedang Anda kerjakan:
[TestCase("Milky Way")]
[TestCase("Andromeda")]
[TestCase("Pinwheel")]
[TestCase("NGC 1300")]
[TestCase("Messier 82")]
public void FetchOnlyRequestedGameRegion(string gameRegion)
{
const int PAGE = 0; // take the first page of results
const int MAX_RESULTS = 10; // sample up to 10 results
// Form the query predicate.
// This expression selects all scores for the provided game region.
Expression<Func<Score, bool>> queryPredicate = score => (score.GameRegion == gameRegion);
// Fetch the scores.
Task<IEnumerable<Score>> scoresTask = _scoreRepository.GetItemsAsync(
queryPredicate, // the predicate defined above
score => 1, // we don't care about the order
PAGE,
MAX_RESULTS
);
IEnumerable<Score> scores = scoresTask.Result;
// Verify that each score's game region matches the provided game region.
Assert.That(scores, Is.All.Matches<Score>(score => score.GameRegion == gameRegion));
}
Anda dapat memfilter papan peringkat dengan kombinasi jenis permainan dan peta game apa pun.
Pengujian ini mengkueri papan peringkat untuk skor tinggi dan memverifikasi bahwa setiap hasil cocok dengan peta game yang disediakan.
Dalam metode pengujian NUnit, TestCase
menyediakan data sebaris yang digunakan untuk menguji metode tersebut. Di sini, NUnit memanggil FetchOnlyRequestedGameRegion
metode pengujian unit, sebagai berikut:
FetchOnlyRequestedGameRegion("Milky Way");
FetchOnlyRequestedGameRegion("Andromeda");
FetchOnlyRequestedGameRegion("Pinwheel");
FetchOnlyRequestedGameRegion("NGC 1300");
FetchOnlyRequestedGameRegion("Messier 82");
Perhatikan panggilan ke metode Assert.That
di akhir pengujian. Pernyataan adalah kondisi atau pernyataan yang Anda nyatakan benar. Jika kondisinya ternyata salah, itu dapat menunjukkan bug dalam kode Anda. NUnit menjalankan setiap metode pengujian menggunakan data sebaris yang Anda tentukan dan merekam hasilnya sebagai pengujian yang lulus atau gagal.
Banyak kerangka kerja pengujian unit menyediakan metode verifikasi yang menyerupai bahasa alami. Metode ini membantu membuat pengujian mudah dibaca dan membantu Anda memetakan pengujian ke persyaratan aplikasi.
Pertimbangkan pernyataan yang dibuat dalam contoh ini:
Assert.That(scores, Is.All.Matches<Score>(score => score.GameRegion == gameRegion));
Anda dapat membaca baris ini sebagai:
Tegaskan bahwa wilayah permainan dari setiap skor yang dikembalikan cocok dengan wilayah permainan yang disediakan.
Berikut adalah proses yang harus diikuti:
- Ambil cabang dari repositori GitHub yang berisi pengujian unit.
- Jalankan pengujian secara lokal untuk memverifikasi bahwa mereka lulus.
- Tambahkan tugas ke konfigurasi alur Anda untuk menjalankan pengujian dan mengumpulkan hasilnya.
- Dorong cabang ke repositori GitHub Anda.
- Tonton proyek Azure Pipelines Anda secara otomatis membangun aplikasi dan menjalankan pengujian.
Ambil cabang dari GitHub
Di sini, Anda akan mengambil unit-tests
cabang dari GitHub dan memeriksa, atau beralih ke cabang itu.
Cabang ini berisi proyek Space Game yang anda kerjakan di modul sebelumnya dan konfigurasi Azure Pipelines untuk memulai.
Di Visual Studio Code, buka terminal terintegrasi.
Jalankan perintah
git
berikut untuk mengambil cabang bernamaunit-tests
dari repositori Microsoft, lalu beralih ke cabang tersebut.git fetch upstream unit-tests git checkout -B unit-tests upstream/unit-tests
Format perintah ini memungkinkan Anda mendapatkan kode pemula dari repositori Microsoft GitHub, yang dikenal sebagai
upstream
. Tak lama, Anda akan mendorong cabang ini ke repositori GitHub Anda, yang dikenal sebagaiorigin
.Sebagai langkah opsional, buka file azure-pipelines.yml di Visual Studio Code dan biasakan diri Anda dengan konfigurasi awal. Konfigurasinya menyerupai yang dasar yang Anda buat di modul Buat alur build dengan Azure Pipelines. Ini hanya membangun konfigurasi Rilis aplikasi.
Jalankan pengujian secara lokal
Sebaiknya jalankan semua pengujian secara lokal sebelum Anda mengirimkan pengujian apa pun ke alur. Anda akan melakukan itu di sini.
Di Visual Studio Code, buka terminal terintegrasi.
Jalankan
dotnet build
untuk membangun setiap proyek dalam solusi.dotnet build --configuration Release
Jalankan perintah
dotnet test
berikut untuk menjalankan pengujian unit:dotnet test --configuration Release --no-build
Bendera
--no-build
menentukan untuk tidak membangun proyek sebelum menjalankannya. Anda tidak perlu membangun proyek karena sudah membuatnya di langkah sebelumnya.Anda akan melihat bahwa kelima tes lulus.
Starting test execution, please wait... A total of 1 test files matched the specified pattern. Passed! - Failed: 0, Passed: 5, Skipped: 0, Total: 5, Duration: 57 ms
Dalam contoh ini, pengujian membutuhkan waktu kurang dari satu detik untuk dijalankan.
Perhatikan bahwa ada lima total tes. Meskipun kami hanya mendefinisikan satu metode pengujian,
FetchOnlyRequestedGameRegion
, pengujian tersebut dijalankan lima kali, sekali untuk setiap peta game seperti yang ditentukan dalamTestCase
data sebaris.Jalankan pengujian kedua kalinya. Kali ini, berikan opsi
--logger
untuk menulis hasilnya ke file log.dotnet test Tailspin.SpaceGame.Web.Tests --configuration Release --no-build --logger trx
Anda melihat dari output bahwa file TRX dibuat di direktori TestResults.
File TRX adalah dokumen XML yang berisi hasil uji coba. Ini adalah format populer untuk hasil pengujian karena Visual Studio dan alat lain dapat membantu Anda memvisualisasikan hasilnya.
Nantinya, Anda akan melihat bagaimana Azure Pipelines dapat membantu Anda memvisualisasikan dan melacak hasil pengujian saat berjalan melalui alur.
Catatan
File TRX tidak dimaksudkan untuk disertakan dalam kontrol sumber. File .gitignore memungkinkan Anda menentukan file sementara dan file lain yang ingin Diabaikan Git. File .gitignore proyek sudah disiapkan untuk mengabaikan apa pun di direktori TestResults.
Sebagai langkah opsional, di Visual Studio Code, buka file DocumentDBRepository_GetItemsAsyncShould.cs dari folder Tailspin.SpaceGame.Web.Tests dan periksa kode pengujian. Bahkan jika Anda tidak tertarik untuk membangun aplikasi .NET secara khusus, Anda mungkin menemukan kode pengujian yang berguna karena menyerupai kode yang mungkin Anda lihat dalam kerangka kerja pengujian unit lainnya.
Menambahkan tugas ke konfigurasi alur Anda
Di sini, Anda akan mengonfigurasi alur build untuk menjalankan pengujian unit dan mengumpulkan hasilnya.
Di Visual Studio Code, ubah azure-pipelines.yml seperti berikut:
trigger: - '*' pool: vmImage: 'ubuntu-20.04' demands: - npm variables: buildConfiguration: 'Release' wwwrootDir: 'Tailspin.SpaceGame.Web/wwwroot' dotnetSdkVersion: '6.x' steps: - task: UseDotNet@2 displayName: 'Use .NET SDK $(dotnetSdkVersion)' inputs: version: '$(dotnetSdkVersion)' - task: Npm@1 displayName: 'Run npm install' inputs: verbose: false - script: './node_modules/.bin/node-sass $(wwwrootDir) --output $(wwwrootDir)' displayName: 'Compile Sass assets' - task: gulp@1 displayName: 'Run gulp tasks' - script: 'echo "$(Build.DefinitionName), $(Build.BuildId), $(Build.BuildNumber)" > buildinfo.txt' displayName: 'Write build info' workingDirectory: $(wwwrootDir) - task: DotNetCoreCLI@2 displayName: 'Restore project dependencies' inputs: command: 'restore' projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'Build the project - $(buildConfiguration)' inputs: command: 'build' arguments: '--no-restore --configuration $(buildConfiguration)' projects: '**/*.csproj' - task: DotNetCoreCLI@2 displayName: 'Run unit tests - $(buildConfiguration)' inputs: command: 'test' arguments: '--no-build --configuration $(buildConfiguration)' publishTestResults: true projects: '**/*.Tests.csproj' - task: DotNetCoreCLI@2 displayName: 'Publish the project - $(buildConfiguration)' inputs: command: 'publish' projects: '**/*.csproj' publishWebProjects: false arguments: '--no-build --configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)/$(buildConfiguration)' zipAfterPublish: true - task: PublishBuildArtifacts@1 displayName: 'Publish Artifact: drop' condition: succeeded()
Versi ini memperkenalkan tugas build
DotNetCoreCLI@2
ini.- task: DotNetCoreCLI@2 displayName: 'Run unit tests - $(buildConfiguration)' inputs: command: 'test' arguments: '--no-build --configuration $(buildConfiguration)' publishTestResults: true projects: '**/*.Tests.csproj'
Tugas build ini menjalankan perintah
dotnet test
.Perhatikan bahwa tugas ini tidak menentukan argumen
--logger trx
yang Anda gunakan saat menjalankan pengujian secara manual. ArgumenpublishTestResults
menambahkannya untuk Anda. Argumen ini memberi tahu alur untuk menghasilkan file TRX ke direktori sementara, yang dapat diakses melalui variabel bawaan$(Agent.TempDirectory)
. Ini juga menerbitkan hasil tugas ke alur.Argumen
projects
menentukan semua proyek C# yang cocok dengan "**/*. Tests.csproj." Bagian "**" cocok dengan semua direktori, dan "*. Bagian Tests.csproj" cocok dengan semua proyek yang nama filenya diakhapi dengan ". Tests.csproj." Cabangunit-tests
hanya berisi satu proyek pengujian unit, Tailspin.SpaceGame.Web.Tests.csproj. Dengan menentukan pola, Anda dapat menjalankan lebih banyak proyek pengujian tanpa perlu memodifikasi konfigurasi build Anda.
Dorong cabang ke GitHub
Di sini, Anda akan mendorong perubahan ke GitHub dan melihat eksekusi alur. Ingatlah bahwa Anda saat ini berada di cabang unit-tests
.
Di terminal terintegrasi, tambahkan azure-pipelines.yml ke indeks, terapkan perubahan, dan dorong cabang hingga GitHub.
git add azure-pipelines.yml git commit -m "Run and publish unit tests" git push origin unit-tests
Tonton Azure Pipelines menjalankan pengujian
Di sini Anda melihat pengujian berjalan di alur lalu memvisualisasikan hasil dari Microsoft Azure Test Plans. Azure Test Plans menyediakan semua alat yang Anda butuhkan untuk berhasil menguji aplikasi Anda. Anda dapat membuat dan menjalankan rencana pengujian manual, menghasilkan pengujian otomatis, dan mengumpulkan umpan balik dari pemangku kepentingan.
Di Azure Pipelines, lacak build melalui setiap langkah.
Anda melihat bahwa tugas Jalankan pengujian unit - Rilis menjalankan pengujian unit seperti yang Anda lakukan secara manual dari baris perintah.
Navigasikan kembali ke ringkasan alur.
Pindah ke tab Pengujian.
Anda melihat ringkasan uji coba. Kelima tes telah lulus.
Di Azure DevOps, pilih Uji Paket, lalu pilih Jalankan.
Anda melihat uji coba terbaru, termasuk yang baru saja Anda jalankan.
Klik dua kali uji coba terbaru.
Anda melihat ringkasan hasil.
Dalam contoh ini, kelima tes telah lulus. Jika ada pengujian yang gagal, Anda dapat membuka tugas build untuk mendapatkan detail selengkapnya.
Anda juga dapat mengunduh file TRX untuk memeriksanya melalui Visual Studio atau alat visualisasi lainnya.
Meskipun Anda hanya menambahkan satu pengujian, ini adalah awal yang baik dan memperbaiki masalah segera. Sekarang, tim memiliki tempat untuk menambahkan lebih banyak tes dan menjalankannya saat mereka meningkatkan proses mereka.
Menggabungkan cabang Anda ke utama
Dalam skenario dunia nyata, jika Anda senang dengan hasilnya, Anda mungkin menggabungkan unit-tests
cabang ke main
, tetapi untuk brevity, kami akan melewati proses itu untuk saat ini.