


Beberapa tahun lalu saya menulis tentang perkara ini, tetapi kurang terperinci. Berikut ialah versi idea yang sama yang lebih halus.
Pengenalan
Ujian unit adalah kebaikan dan keburukan kepada pembangun. Mereka membenarkan ujian pantas kefungsian, contoh penggunaan yang boleh dibaca, percubaan pantas senario untuk komponen yang terlibat sahaja. Tetapi ia juga boleh menjadi kucar-kacir, memerlukan penyelenggaraan dan kemas kini dengan setiap perubahan kod dan, apabila dilakukan dengan malas, tidak boleh menyembunyikan pepijat daripada mendedahkannya.
Saya rasa sebab ujian unit begitu sukar adalah kerana ia dikaitkan dengan ujian, sesuatu selain daripada penulisan kod, dan juga ujian unit ditulis dengan cara yang bertentangan dengan kebanyakan kod lain yang kami tulis.
Dalam siaran ini, saya akan memberi anda corak mudah menulis ujian unit yang akan meningkatkan semua faedah, sambil menghapuskan kebanyakan disonans kognitif dengan kod biasa. Ujian unit akan kekal boleh dibaca dan fleksibel, sambil mengurangkan kod pendua dan tidak menambah kebergantungan tambahan.
Bagaimana untuk ujian unit
Tetapi pertama sekali, mari kita tentukan suite ujian unit yang baik.
Untuk menguji kelas dengan betul, ia perlu ditulis dengan cara tertentu. Dalam siaran ini, kami akan merangkumi kelas menggunakan suntikan pembina untuk kebergantungan, yang merupakan cara saya yang disyorkan untuk melakukan suntikan kebergantungan.
Kemudian, untuk mengujinya, kita perlu:
- meliputi senario positif - apabila kelas melakukan perkara yang sepatutnya dilakukan, dengan pelbagai kombinasi tetapan dan parameter input untuk merangkumi keseluruhan fungsi
- tutup senario negatif - apabila kelas gagal dengan cara yang betul apabila persediaan atau parameter input salah
- ejek semua kebergantungan luar
- simpan semua persediaan ujian, tindakan dan penegasan dalam ujian yang sama (yang biasanya dipanggil struktur Susun-Tindakan-Tegaskan)
Tetapi itu lebih mudah diucapkan daripada dilakukan, kerana ia juga membayangkan:
- menyediakan kebergantungan yang sama untuk setiap ujian, dengan itu menyalin dan menampal banyak kod
- menyediakan senario yang hampir sama, dengan hanya satu perubahan antara dua ujian, sekali lagi mengulangi banyak kod
- mengeneralisasikan dan merangkum apa-apa, itulah yang biasanya dilakukan oleh pembangun dalam semua kod mereka
- menulis banyak kes negatif untuk beberapa kes positif, yang rasanya seperti mempunyai lebih banyak kod ujian daripada kod berfungsi
- perlu mengemas kini semua ujian ini untuk setiap perubahan pada kelas yang diuji
Siapa suka itu?
Penyelesaian
Penyelesaian adalah dengan menggunakan corak perisian pembina untuk mencipta ujian yang cair, fleksibel dan boleh dibaca dalam struktur Susun-Bertindak-Tegas, sambil merangkum kod persediaan dalam kelas yang melengkapkan suite ujian unit untuk perkhidmatan tertentu. Saya memanggil ini corak MockManager.
Mari kita mulakan dengan contoh mudah:
// the tested class public class Calculator { private readonly ITokenParser tokenParser; private readonly IMathOperationFactory operationFactory; private readonly ICache cache; private readonly ILogger logger; public Calculator( ITokenParser tokenParser, IMathOperationFactory operationFactory, ICache cache, ILogger logger) { this.tokenParser = tokenParser; this.operationFactory = operationFactory; this.cache = cache; this.logger = logger; } public int Calculate(string input) { var result = cache.Get(input); if (result.HasValue) { logger.LogInformation("from cache"); return result.Value; } var tokens = tokenParser.Parse(input); IOperation operation = null; foreach(var token in tokens) { if (operation is null) { operation = operationFactory.GetOperation(token.OperationType); continue; } if (result is null) { result = token.Value; continue; } else { if (result is null) { throw new InvalidOperationException("Could not calculate result"); } result = operation.Execute(result.Value, token.Value); operation = null; } } cache.Set(input, result.Value); logger.LogInformation("from operation"); return result.Value; } }
Ini adalah kalkulator, seperti tradisi. Ia menerima rentetan dan mengembalikan nilai integer. Ia juga menyimpan hasil carian untuk input tertentu, dan log beberapa perkara. Operasi sebenar sedang diabstrak oleh IMathOperationFactory dan rentetan input diterjemahkan ke dalam token oleh ITokenParser. Jangan risau, ini bukan kelas sebenar, hanya contoh. Mari lihat ujian "tradisional":
[TestMethod] public void Calculate_AdditionWorks() { // Arrange var tokenParserMock = new Mock<itokenparser>(); tokenParserMock .Setup(m => m.Parse(It.IsAny<string>())) .Returns( new List<calculatortoken> { CalculatorToken.Addition, CalculatorToken.From(1), CalculatorToken.From(1) } ); var mathOperationFactoryMock = new Mock<imathoperationfactory>(); var operationMock = new Mock<ioperation>(); operationMock .Setup(m => m.Execute(1, 1)) .Returns(2); mathOperationFactoryMock .Setup(m => m.GetOperation(OperationType.Add)) .Returns(operationMock.Object); var cacheMock = new Mock<icache>(); var loggerMock = new Mock<ilogger>(); var service = new Calculator( tokenParserMock.Object, mathOperationFactoryMock.Object, cacheMock.Object, loggerMock.Object); // Act service.Calculate(""); //Assert mathOperationFactoryMock .Verify(m => m.GetOperation(OperationType.Add), Times.Once); operationMock .Verify(m => m.Execute(1, 1), Times.Once); } </ilogger></icache></ioperation></imathoperationfactory></calculatortoken></string></itokenparser>
Jom bongkar sikit. Kami terpaksa mengisytiharkan olok-olok untuk setiap pergantungan pembina, walaupun kami sebenarnya tidak mengambil berat tentang pembalak atau cache, sebagai contoh. Kami juga terpaksa menyediakan kaedah olok-olok yang mengembalikan olok-olok lain, dalam kes kilang operasi.
Dalam ujian khusus ini, kebanyakannya kami menulis persediaan, satu baris Act dan dua baris Assert. Lebih-lebih lagi, jika kami ingin menguji cara cache berfungsi di dalam kelas, kami perlu menyalin tampal keseluruhannya dan hanya mengubah cara kami menyediakan mock cache.
Dan terdapat ujian negatif untuk dipertimbangkan. Saya telah melihat banyak ujian negatif melakukan sesuatu seperti: "sediakan hanya apa yang sepatutnya gagal. uji bahawa ia gagal", yang memperkenalkan banyak masalah, terutamanya kerana ia mungkin gagal untuk sebab yang berbeza dan kebanyakan masa ujian ini mengikuti pelaksanaan dalaman kelas dan bukannya keperluannya. Ujian negatif yang betul sebenarnya adalah ujian positif sepenuhnya dengan hanya satu keadaan yang salah. Tidak begitu di sini, untuk kesederhanaan.
Jadi, tanpa berlengah lagi, inilah ujian yang sama, tetapi dengan MockManager:
[TestMethod] public void Calculate_AdditionWorks_MockManager() { // Arrange var mockManager = new CalculatorMockManager() .WithParsedTokens(new List<calculatortoken> { CalculatorToken.Addition, CalculatorToken.From(1), CalculatorToken.From(1) }) .WithOperation(OperationType.Add, 1, 1, 2); var service = mockManager.GetService(); // Act service.Calculate(""); //Assert mockManager .VerifyOperationExecute(OperationType.Add, 1, 1, Times.Once); } </calculatortoken>
Membongkar, tidak ada menyebut tentang cache atau logger, kerana kami tidak memerlukan sebarang persediaan di sana. Semuanya dibungkus dan boleh dibaca. Salin tampal ini dan menukar beberapa parameter atau beberapa baris tidak lagi hodoh. Terdapat tiga kaedah yang dilaksanakan dalam Arrange, satu dalam Act dan satu dalam Assert. Hanya butiran ejekan yang ringkas sahaja yang disarikan: rangka kerja Moq tidak disebutkan di sini. Malah, ujian ini akan kelihatan sama tanpa mengira rangka kerja mengejek yang diputuskan untuk digunakan.
Mari kita lihat kelas MockManager. Sekarang ini akan kelihatan rumit, tetapi ingat bahawa kami hanya menulis ini sekali dan menggunakannya berkali-kali. Keseluruhan kerumitan kelas ada untuk menjadikan ujian unit boleh dibaca oleh manusia, mudah difahami, dikemas kini dan diselenggara.
public class CalculatorMockManager { private readonly Dictionary<operationtype>> operationMocks = new(); public Mock<itokenparser> TokenParserMock { get; } = new(); public Mock<imathoperationfactory> MathOperationFactoryMock { get; } = new(); public Mock<icache> CacheMock { get; } = new(); public Mock<ilogger> LoggerMock { get; } = new(); public CalculatorMockManager WithParsedTokens(List<calculatortoken> tokens) { TokenParserMock .Setup(m => m.Parse(It.IsAny<string>())) .Returns( new List<calculatortoken> { CalculatorToken.Addition, CalculatorToken.From(1), CalculatorToken.From(1) } ); return this; } public CalculatorMockManager WithOperation(OperationType operationType, int v1, int v2, int result) { var operationMock = new Mock<ioperation>(); operationMock .Setup(m => m.Execute(v1, v2)) .Returns(result); MathOperationFactoryMock .Setup(m => m.GetOperation(operationType)) .Returns(operationMock.Object); operationMocks[operationType] = operationMock; return this; } public Calculator GetService() { return new Calculator( TokenParserMock.Object, MathOperationFactoryMock.Object, CacheMock.Object, LoggerMock.Object ); } public CalculatorMockManager VerifyOperationExecute(OperationType operationType, int v1, int v2, Func<times> times) { MathOperationFactoryMock .Verify(m => m.GetOperation(operationType), Times.AtLeastOnce); var operationMock = operationMocks[operationType]; operationMock .Verify(m => m.Execute(v1, v2), times); return this; } } </times></ioperation></calculatortoken></string></calculatortoken></ilogger></icache></imathoperationfactory></itokenparser></operationtype>
Semua olok-olok yang diperlukan untuk kelas ujian diisytiharkan sebagai harta awam, membenarkan sebarang penyesuaian ujian unit. Terdapat kaedah GetService, yang akan sentiasa mengembalikan contoh kelas yang diuji, dengan semua kebergantungan diejek sepenuhnya. Kemudian terdapat kaedah With* yang secara atom menyediakan pelbagai senario dan sentiasa mengembalikan pengurus olok-olok, supaya mereka boleh dirantai. Anda juga boleh mempunyai kaedah khusus untuk penegasan, walaupun dalam kebanyakan kes anda akan membandingkan beberapa output dengan nilai yang dijangkakan, jadi ini di sini hanya untuk mengabsahkan kaedah Sahkan rangka kerja Moq.
Kesimpulan
Corak ini kini menjajarkan penulisan ujian dengan penulisan kod:
- abstrak perkara yang anda tidak kisah dalam sebarang konteks
- tulis sekali dan guna berkali-kali
- Kod pendokumentasian diri yang boleh dibaca oleh manusia
- kaedah kecil dengan kerumitan cyclomatic yang rendah
- penulisan kod intuitif
Menulis ujian unit sekarang adalah remeh dan konsisten:
- segera pengurus olok-olok kelas yang anda ingin uji (atau tulis satu berdasarkan langkah di atas)
- karang senario khusus untuk ujian (dengan auto lengkap untuk langkah senario yang sedia ada)
- laksanakan kaedah yang anda ingin uji dengan parameter ujian
- semak semuanya adalah seperti yang diharapkan
Pengabstrakan tidak berhenti pada rangka kerja mengejek. Corak yang sama boleh digunakan dalam setiap bahasa pengaturcaraan! Binaan pengurus olok-olok akan sangat berbeza untuk TypeScript atau JavaScript atau sesuatu yang lain, tetapi ujian unit akan kelihatan dengan cara yang sama.
Semoga ini membantu!
Atas ialah kandungan terperinci MockManager dalam ujian unit - corak pembina yang digunakan untuk olok-olok. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Bekerja dengan struktur data XML di C boleh menggunakan perpustakaan TinyXML atau PugixML. 1) Gunakan perpustakaan PugixML untuk menghuraikan dan menghasilkan fail XML. 2) Mengendalikan elemen XML bersarang kompleks, seperti maklumat buku. 3) Mengoptimumkan kod pemprosesan XML, dan disyorkan untuk menggunakan perpustakaan yang cekap dan parsing streaming. Melalui langkah -langkah ini, data XML dapat diproses dengan cekap.

C masih menguasai pengoptimuman prestasi kerana pengurusan memori peringkat rendah dan keupayaan pelaksanaan yang cekap menjadikannya sangat diperlukan dalam pembangunan permainan, sistem transaksi kewangan dan sistem tertanam. Khususnya, ia ditunjukkan sebagai: 1) dalam pembangunan permainan, pengurusan memori peringkat rendah C dan keupayaan pelaksanaan yang cekap menjadikannya bahasa pilihan untuk pembangunan enjin permainan; 2) Dalam sistem transaksi kewangan, kelebihan prestasi C memastikan latensi yang sangat rendah dan throughput yang tinggi; 3) Dalam sistem tertanam, pengurusan memori peringkat rendah C dan keupayaan pelaksanaan yang cekap menjadikannya sangat popular dalam persekitaran yang terkawal sumber.

Pilihan kerangka C XML harus berdasarkan keperluan projek. 1) TinyXML sesuai untuk persekitaran yang terkawal sumber, 2) PugixML sesuai untuk keperluan berprestasi tinggi, 3) Xerces-C menyokong pengesahan XMLSchema kompleks, dan prestasi, kemudahan penggunaan dan lesen mesti dipertimbangkan ketika memilih.

C# sesuai untuk projek yang memerlukan kecekapan pembangunan dan keselamatan jenis, manakala C sesuai untuk projek yang memerlukan prestasi tinggi dan kawalan perkakasan. 1) C# menyediakan koleksi sampah dan LINQ, sesuai untuk aplikasi perusahaan dan pembangunan Windows. 2) C dikenali dengan prestasi tinggi dan kawalan asasnya, dan digunakan secara meluas dalam pengaturcaraan permainan dan sistem.

Pengoptimuman kod C boleh dicapai melalui strategi berikut: 1. Menguruskan memori secara manual untuk penggunaan pengoptimuman; 2. Tulis kod yang mematuhi peraturan pengoptimuman pengkompil; 3. Pilih algoritma dan struktur data yang sesuai; 4. Gunakan fungsi inline untuk mengurangkan overhead panggilan; 5. Memohon template metaprogramming untuk mengoptimumkan pada masa penyusunan; 6. Elakkan penyalinan yang tidak perlu, gunakan semantik bergerak dan parameter rujukan; 7. Gunakan Const dengan betul untuk membantu pengoptimuman pengkompil; 8. Pilih struktur data yang sesuai, seperti STD :: vektor.

Kata kunci yang tidak menentu dalam C digunakan untuk memaklumkan pengkompil bahawa nilai pembolehubah boleh diubah di luar kawalan kod dan oleh itu tidak dapat dioptimumkan. 1) Ia sering digunakan untuk membaca pembolehubah yang boleh diubahsuai oleh perkakasan atau program perkhidmatan mengganggu, seperti keadaan sensor. 2) Tidak menentu tidak dapat menjamin keselamatan multi-thread, dan harus menggunakan kunci mutex atau operasi atom. 3) Menggunakan tidak menentu boleh menyebabkan prestasi sedikit berkurangan, tetapi memastikan ketepatan program.

Mengukur prestasi thread di C boleh menggunakan alat masa, alat analisis prestasi, dan pemasa tersuai di perpustakaan standard. 1. Gunakan perpustakaan untuk mengukur masa pelaksanaan. 2. Gunakan GPROF untuk analisis prestasi. Langkah -langkah termasuk menambah pilihan -pg semasa penyusunan, menjalankan program untuk menghasilkan fail gmon.out, dan menghasilkan laporan prestasi. 3. Gunakan modul Callgrind Valgrind untuk melakukan analisis yang lebih terperinci. Langkah -langkah termasuk menjalankan program untuk menghasilkan fail callgrind.out dan melihat hasil menggunakan kcachegrind. 4. Pemasa tersuai secara fleksibel dapat mengukur masa pelaksanaan segmen kod tertentu. Kaedah ini membantu memahami sepenuhnya prestasi benang dan mengoptimumkan kod.

Menggunakan perpustakaan Chrono di C membolehkan anda mengawal selang masa dan masa dengan lebih tepat. Mari kita meneroka pesona perpustakaan ini. Perpustakaan Chrono C adalah sebahagian daripada Perpustakaan Standard, yang menyediakan cara moden untuk menangani selang waktu dan masa. Bagi pengaturcara yang telah menderita dari masa. H dan CTime, Chrono tidak diragukan lagi. Ia bukan sahaja meningkatkan kebolehbacaan dan mengekalkan kod, tetapi juga memberikan ketepatan dan fleksibiliti yang lebih tinggi. Mari kita mulakan dengan asas -asas. Perpustakaan Chrono terutamanya termasuk komponen utama berikut: STD :: Chrono :: System_Clock: Mewakili jam sistem, yang digunakan untuk mendapatkan masa semasa. Std :: Chron


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Dreamweaver Mac版
Alat pembangunan web visual

Versi Mac WebStorm
Alat pembangunan JavaScript yang berguna

MinGW - GNU Minimalis untuk Windows
Projek ini dalam proses untuk dipindahkan ke osdn.net/projects/mingw, anda boleh terus mengikuti kami di sana. MinGW: Port Windows asli bagi GNU Compiler Collection (GCC), perpustakaan import yang boleh diedarkan secara bebas dan fail pengepala untuk membina aplikasi Windows asli termasuk sambungan kepada masa jalan MSVC untuk menyokong fungsi C99. Semua perisian MinGW boleh dijalankan pada platform Windows 64-bit.

EditPlus versi Cina retak
Saiz kecil, penyerlahan sintaks, tidak menyokong fungsi gesaan kod

Penyesuai Pelayan SAP NetWeaver untuk Eclipse
Integrasikan Eclipse dengan pelayan aplikasi SAP NetWeaver.
