Bagaimana Anda tahu apa yang harus diuji ketika menulis unit test? [Tutup]


127

Menggunakan C #, saya perlu kelas Useryang memiliki nama pengguna, kata sandi, bendera aktif, nama depan, nama belakang, nama lengkap, dll.

Harus ada metode untuk mengotentikasi dan menyimpan pengguna. Apakah saya hanya menulis tes untuk metodenya? Dan apakah saya perlu khawatir tentang pengujian properti karena mereka. Net pengambil dan setter?


Posting ini akan membantu mempersempit pertanyaan yang lebih luas: Earnestengineer.blogspot.com/2018/03/... Anda dapat mengambil panduan ini untuk memfokuskan pertanyaan Anda
Lindsay Morsillo

Perlu diingat kata sandi tidak boleh disimpan sebagai plaintext.
Tn. Anderson

Jawaban:


131

Banyak tanggapan bagus untuk ini juga pada pertanyaan saya: " Memulai TDD - Tantangan? Solusi? Rekomendasi? "

Bolehkah saya juga merekomendasikan untuk melihat posting blog saya (yang sebagian terinspirasi oleh pertanyaan saya), saya sudah mendapat tanggapan yang bagus tentang itu. Yaitu:

Saya tidak tahu harus mulai dari mana?

  • Mulai dari awal. Pikirkan tentang tes menulis hanya ketika Anda menulis kode baru. Ini dapat berfungsi kembali dengan kode lama, atau fitur yang sama sekali baru.
  • Mulai dari yang sederhana. Jangan lari dan mencoba membuat kerangka kerja Anda menjadi TDD-esque. Debug. Assert berfungsi dengan baik. Gunakan itu sebagai titik awal. Itu tidak mengacaukan proyek Anda atau membuat dependensi.
  • Mulai positif. Anda mencoba meningkatkan keahlian Anda, merasa senang tentang hal itu. Saya telah melihat banyak pengembang di luar sana yang senang stagnan dan tidak mencoba hal-hal baru untuk memperbaiki diri. Anda melakukan hal yang benar, ingat ini dan itu akan membantu menghentikan Anda dari menyerah.
  • Mulai siap menghadapi tantangan. Sangat sulit untuk memulai pengujian. Harapkan tantangan, tapi ingat - tantangan bisa diatasi.

Hanya Tes Untuk Apa Yang Anda Harapkan

Saya memiliki masalah nyata ketika pertama kali memulai karena saya terus-menerus duduk di sana mencoba mencari tahu setiap masalah yang mungkin terjadi dan kemudian mencoba untuk mengujinya dan memperbaikinya. Ini adalah cara cepat untuk sakit kepala. Pengujian harus menjadi proses YAGNI yang nyata. Jika Anda tahu ada masalah, maka tulis tes untuk itu. Kalau tidak, jangan repot-repot.

Hanya Uji Satu Hal

Setiap test case seharusnya hanya menguji satu hal. Jika Anda mendapati diri Anda memasukkan "dan" dalam nama kasus uji, Anda melakukan kesalahan.

Saya harap ini berarti kita dapat beralih dari "getter dan setter" :)


2
"Jika kamu tahu ada masalah, maka tulislah tes untuk itu. Kalau tidak, jangan repot-repot." Saya tidak setuju dengan cara ini. Saya mendapat kesan bahwa unit test harus mencakup semua jalur eksekusi yang mungkin.
Corin Blaikie

3
Sementara beberapa mungkin menganjurkan hal-hal seperti itu, saya pribadi tidak. Sebanyak 90% sakit kepala saya berasal dari hanya mencoba melakukan "segalanya". Saya mengatakan tes untuk apa yang Anda harapkan terjadi (sehingga Anda tahu Anda mendapatkan nilai yang benar kembali) tetapi jangan mencoba dan mencari tahu semuanya. YAGNI.
Rob Cooper

4
Saya juga mendukung pendekatan "uji bug Anda". Jika kita semua memiliki waktu dan kesabaran tanpa batas, kami akan menguji setiap jalur eksekusi yang memungkinkan. Tapi kami tidak, jadi Anda harus menghabiskan usaha Anda di mana itu akan memiliki efek terbesar.
Schwern

63

Uji kode Anda, bukan bahasa.

Tes unit seperti:

Integer i = new Integer(7);
assert (i.instanceOf(integer));

hanya berguna jika Anda menulis kompiler dan ada kemungkinan tidak nol bahwa instanceofmetode Anda tidak berfungsi.

Jangan menguji hal-hal yang bisa Anda andalkan pada bahasa yang digunakan. Dalam kasus Anda, saya akan fokus pada otentikasi Anda dan menyimpan metode - dan saya akan menulis tes yang memastikan mereka dapat menangani nilai nol di salah satu atau semua bidang itu dengan anggun.


1
Good Point on "Dont test the framework" - Sesuatu yang saya dapatkan juga ketika baru dalam hal ini. Diberi +1 :)
Rob Cooper

38

Ini membuat saya memasuki unit testing dan itu membuat saya sangat bahagia

Kami baru mulai melakukan pengujian unit. Untuk waktu yang lama saya tahu akan baik untuk mulai melakukannya tetapi saya tidak tahu bagaimana memulainya dan yang lebih penting apa yang harus diuji.

Kemudian kami harus menulis ulang sepotong kode penting dalam program akuntansi kami. Bagian ini sangat kompleks karena melibatkan banyak skenario yang berbeda. Bagian yang saya bicarakan adalah metode untuk membayar penjualan dan / atau faktur pembelian yang sudah dimasukkan ke dalam sistem akuntansi.

Saya hanya tidak tahu bagaimana memulai mengkodekannya, karena ada begitu banyak opsi pembayaran yang berbeda. Faktur bisa menjadi $ 100 tetapi pelanggan hanya mentransfer $ 99. Mungkin Anda telah mengirim faktur penjualan ke pelanggan tetapi Anda juga telah membeli dari pelanggan itu. Jadi Anda menjualnya seharga $ 300 tetapi Anda membeli seharga $ 100. Anda dapat mengharapkan pelanggan membayar Anda $ 200 untuk menyelesaikan saldo. Dan bagaimana jika Anda menjual seharga $ 500 tetapi pelanggan hanya membayar Anda $ 250?

Jadi saya punya masalah yang sangat kompleks untuk dipecahkan dengan banyak kemungkinan bahwa satu skenario akan bekerja dengan sempurna tetapi akan salah pada jenis kombinasi invocie / pembayaran lainnya.

Di sinilah unit testing datang untuk menyelamatkan.

Saya mulai menulis (di dalam kode uji) metode untuk membuat daftar faktur, baik untuk penjualan maupun pembelian. Lalu saya menulis metode kedua untuk membuat pembayaran aktual. Biasanya pengguna akan memasukkan informasi itu melalui antarmuka pengguna.

Lalu saya membuat TestMethod pertama, menguji pembayaran yang sangat sederhana dari satu faktur tanpa diskon pembayaran. Semua tindakan dalam sistem akan terjadi ketika pembayaran bank akan disimpan ke database. Seperti yang Anda lihat saya membuat faktur, membuat pembayaran (transaksi bank) dan menyimpan transaksi ke disk. Dalam pernyataan saya, saya memasukkan angka yang benar yang harus berakhir dalam transaksi Bank dan dalam Faktur tertaut. Saya memeriksa jumlah pembayaran, jumlah pembayaran, jumlah diskon dan saldo faktur setelah transaksi.

Setelah tes berjalan saya akan pergi ke database dan periksa apakah yang saya harapkan ada di sana.

Setelah saya menulis tes, saya mulai mengkode metode pembayaran (bagian dari kelas BankHeader). Dalam pengkodean saya hanya repot dengan kode untuk membuat tes lulus pertama. Saya belum memikirkan skenario lain yang lebih kompleks.

Saya menjalankan tes pertama, memperbaiki bug kecil sampai tes saya akan berlalu.

Kemudian saya mulai menulis tes kedua, kali ini bekerja dengan diskon pembayaran. Setelah saya menulis tes saya memodifikasi metode pembayaran untuk mendukung diskon.

Saat menguji kebenaran dengan diskon pembayaran, saya juga menguji pembayaran sederhana. Kedua tes harus lulus tentu saja.

Kemudian saya bekerja sampai ke skenario yang lebih kompleks.

1) Pikirkan skenario baru

2) Tulis tes untuk skenario itu

3) Jalankan tes tunggal untuk melihat apakah itu akan lulus

4) Jika tidak, saya akan men-debug dan memodifikasi kode sampai lulus.

5) Saat memodifikasi kode saya terus menjalankan semua tes

Inilah cara saya berhasil membuat metode pembayaran yang sangat rumit. Tanpa pengujian unit, saya tidak tahu cara memulai pengkodean, masalahnya tampak luar biasa. Dengan pengujian saya bisa mulai dengan metode sederhana dan memperluasnya langkah demi langkah dengan jaminan bahwa skenario yang lebih sederhana masih akan berfungsi.

Saya yakin bahwa menggunakan pengujian unit menyelamatkan saya beberapa hari (atau minggu) pengkodean dan lebih atau kurang menjamin kebenaran metode saya.

Jika nanti saya memikirkan skenario baru, saya bisa menambahkannya ke tes untuk melihat apakah itu berfungsi atau tidak. Jika tidak, saya dapat memodifikasi kode tetapi masih memastikan skenario lain masih berfungsi dengan benar. Ini akan menghemat hari dan hari dalam fase pemeliharaan dan perbaikan bug.

Ya, bahkan kode yang diuji masih dapat memiliki bug jika pengguna melakukan hal-hal yang tidak Anda pikirkan atau mencegahnya melakukannya

Berikut adalah beberapa tes yang saya buat untuk menguji metode pembayaran saya.

public class TestPayments
{
    InvoiceDiaryHeader invoiceHeader = null;
    InvoiceDiaryDetail invoiceDetail = null;
    BankCashDiaryHeader bankHeader = null;
    BankCashDiaryDetail bankDetail = null;



    public InvoiceDiaryHeader CreateSales(string amountIncVat, bool sales, int invoiceNumber, string date)
    {
        ......
        ......
    }

    public BankCashDiaryHeader CreateMultiplePayments(IList<InvoiceDiaryHeader> invoices, int headerNumber, decimal amount, decimal discount)
    {
       ......
       ......
       ......
    }


    [TestMethod]
    public void TestSingleSalesPaymentNoDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 1, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 1, 119.00M, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(119M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(0M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSingleSalesPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 2, "01-09-2008"));
        bankHeader = CreateMultiplePayments(list, 2, 118.00M, 1M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(1, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(1M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
    }

    [TestMethod]
    [ExpectedException(typeof(ApplicationException))]
    public void TestDuplicateInvoiceNumber()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("100", true, 2, "01-09-2008"));
        list.Add(CreateSales("200", true, 2, "01-09-2008"));

        bankHeader = CreateMultiplePayments(list, 3, 300, 0);
        bankHeader.Save();
        Assert.Fail("expected an ApplicationException");
    }

    [TestMethod]
    public void TestMultipleSalesPaymentWithPaymentDiscount()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("119", true, 11, "01-09-2008"));
        list.Add(CreateSales("400", true, 12, "02-09-2008"));
        list.Add(CreateSales("600", true, 13, "03-09-2008"));
        list.Add(CreateSales("25,40", true, 14, "04-09-2008"));

        bankHeader = CreateMultiplePayments(list, 5, 1144.00M, 0.40M);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(4, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(118.60M, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(400, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(600, bankHeader.BankCashDetails[0].Payments[2].PaymentAmount);
        Assert.AreEqual(25.40M, bankHeader.BankCashDetails[0].Payments[3].PaymentAmount);

        Assert.AreEqual(0.40M, bankHeader.BankCashDetails[0].Payments[0].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].PaymentDiscount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].PaymentDiscount);

        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[2].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
    }

    [TestMethod]
    public void TestSettlement()
    {
        IList<InvoiceDiaryHeader> list = new List<InvoiceDiaryHeader>();
        list.Add(CreateSales("300", true, 43, "01-09-2008")); //Sales
        list.Add(CreateSales("100", false, 6453, "02-09-2008")); //Purchase

        bankHeader = CreateMultiplePayments(list, 22, 200, 0);
        bankHeader.Save();

        Assert.AreEqual(1, bankHeader.BankCashDetails.Count);
        Assert.AreEqual(2, bankHeader.BankCashDetails[0].Payments.Count);
        Assert.AreEqual(300, bankHeader.BankCashDetails[0].Payments[0].PaymentAmount);
        Assert.AreEqual(-100, bankHeader.BankCashDetails[0].Payments[1].PaymentAmount);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[0].InvoiceHeader.Balance);
        Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[1].InvoiceHeader.Balance);
    }

1
Menemukan bug dalam pengujian unit Anda! Anda mengulangi baris ini alih-alih memasukkan 2 di salah satu dari mereka:Assert.AreEqual(0, bankHeader.BankCashDetails[0].Payments[3].InvoiceHeader.Balance);
Ryan Peschel

2
Anda berkata: "Setelah tes berjalan saya akan pergi ke database dan periksa apakah apa yang saya harapkan ada di sana." Ini adalah contoh yang baik dari tes integrasi antara komponen sistem Anda - bukan tes unit yang terisolasi dari sepotong kode.
JTech

2
Anda juga melanggar aturan lebih dari satu Ketegasan per tes.
Steve

13

Jika mereka benar-benar sepele, maka jangan repot-repot menguji. Misalnya, jika diterapkan seperti ini;

public class User
{
    public string Username { get; set; }
    public string Password { get; set; }
}

Jika, di sisi lain, Anda melakukan sesuatu yang pintar, (seperti mengenkripsi dan mendekripsi kata sandi dalam pengambil / penyetel) maka berikan tes.


10

Aturannya adalah Anda harus menguji setiap bagian logika yang Anda tulis. Jika Anda menerapkan beberapa fungsi spesifik dalam getter dan setter saya pikir mereka layak untuk diuji. Jika mereka hanya memberikan nilai ke beberapa bidang pribadi, jangan repot-repot.


6

Pertanyaan ini tampaknya menjadi pertanyaan di mana orang dapat menentukan metode apa yang diuji dan mana yang tidak.

Setter dan pengambil untuk penugasan nilai telah dibuat dengan konsistensi dan pertumbuhan masa depan dalam pikiran, dan meramalkan bahwa beberapa waktu kemudian pembuat setter / pengambil dapat berkembang menjadi operasi yang lebih kompleks. Masuk akal untuk menerapkan unit test terhadap metode-metode itu, juga demi konsistensi dan pertumbuhan di masa depan.

Keandalan kode, terutama saat mengalami perubahan untuk menambah fungsionalitas tambahan, adalah tujuan utama. Saya tidak mengetahui ada orang yang pernah dipecat karena memasukkan setter / getter dalam metodologi pengujian, tetapi saya yakin ada orang yang berharap mereka telah menguji metode yang terakhir mereka sadari atau ingat adalah set / pembungkus sederhana tetapi tidak ada lagi kasusnya.

Mungkin anggota tim lain memperluas metode set / get untuk memasukkan logika yang sekarang perlu diuji tetapi tidak kemudian membuat tes. Tapi sekarang kode Anda memanggil metode ini dan Anda tidak tahu mereka berubah dan perlu pengujian mendalam, dan pengujian yang Anda lakukan dalam pengembangan dan QA tidak memicu cacat, tetapi data bisnis nyata pada hari pertama rilis tidak memicu itu.

Kedua rekan satu tim sekarang akan berdebat tentang siapa yang menjatuhkan bola dan gagal melakukan tes unit ketika set / mendapat morphed untuk memasukkan logika yang bisa gagal tetapi tidak dicakup oleh tes unit. Rekan setim yang awalnya menulis set / mendapat akan memiliki waktu yang lebih mudah keluar dari clean ini jika tes dilaksanakan dari hari pertama pada set / dapatkan sederhana.

Pendapat saya adalah bahwa beberapa menit waktu "terbuang" yang mencakup SEMUA metode dengan tes unit, bahkan yang sepele, dapat menghemat berhari-hari sakit kepala di jalan dan kehilangan uang / reputasi bisnis dan kehilangan pekerjaan seseorang.

Dan fakta bahwa Anda membungkus metode sepele dengan unit test dapat dilihat oleh rekan setim junior ketika mereka mengubah metode sepele menjadi yang non-sepele dan mendorong mereka untuk memperbarui tes, dan sekarang tidak ada yang bermasalah karena cacat itu terkandung dari mencapai produksi.

Cara kita kode, dan disiplin yang dapat dilihat dari kode kita, dapat membantu orang lain.


4

Jawaban kanonik lainnya. Saya percaya ini dari Ron Jeffries:

Hanya uji kode yang ingin Anda kerjakan.


3

Menguji kode boilerplate adalah buang-buang waktu, tetapi seperti yang dikatakan Slavo, jika Anda menambahkan efek samping pada getter / setter Anda, maka Anda harus menulis tes untuk menyertai fungsi itu.

Jika Anda melakukan pengembangan yang digerakkan oleh tes, Anda harus menulis kontrak (misalnya antarmuka) terlebih dahulu, kemudian menulis tes untuk melatih antarmuka yang mendokumentasikan hasil / perilaku yang diharapkan. Kemudian tulis metode Anda sendiri, tanpa menyentuh kode di unit test Anda. Terakhir, ambil alat cakupan kode dan pastikan tes Anda menggunakan semua jalur logika dalam kode Anda.


3

Benar-benar kode sepele seperti getter dan setter yang tidak memiliki perilaku ekstra daripada menetapkan bidang pribadi terlalu sulit untuk diuji. Dalam 3.0 C # bahkan memiliki beberapa gula sintaksis di mana kompiler menangani bidang pribadi sehingga Anda tidak perlu memprogramnya.

Saya biasanya menulis banyak tes yang sangat sederhana untuk memverifikasi perilaku yang saya harapkan dari kelas saya. Bahkan jika itu hal-hal sederhana seperti menambahkan dua angka. Saya banyak beralih antara menulis tes sederhana dan menulis beberapa baris kode. Alasan untuk ini adalah bahwa saya kemudian dapat mengubah kode tanpa takut saya memecahkan hal-hal yang saya tidak pikirkan.


Senang Anda membuat poin bagus dari prinsip KISS .. Saya sering memiliki tes yang secara harfiah seperti 2-3 baris kode, sangat kecil, tes sederhana. Mudah grok dan sulit dihancurkan :) +1'ed
Rob Cooper

3

Anda harus menguji semuanya. Saat ini Anda memiliki getter dan setter, tetapi suatu hari Anda mungkin akan mengubahnya, mungkin untuk melakukan validasi atau yang lainnya. Tes yang Anda tulis hari ini akan digunakan besok untuk memastikan semuanya berjalan seperti biasa. Saat Anda menulis tes, Anda harus melupakan pertimbangan seperti "sekarang ini sepele". Dalam konteks lincah atau digerakkan oleh tes Anda harus menguji dengan asumsi refactoring masa depan. Juga, apakah Anda mencoba memasukkan nilai yang sangat aneh seperti string yang sangat panjang, atau konten "buruk" lainnya? Seharusnya Anda ... jangan pernah berasumsi betapa buruknya kode Anda dapat disalahgunakan di masa depan.

Secara umum saya menemukan bahwa menulis tes pengguna yang luas di satu sisi, melelahkan. Di sisi lain, meskipun selalu memberi Anda wawasan yang sangat berharga tentang bagaimana aplikasi Anda harus bekerja dan membantu Anda membuang asumsi mudah (dan salah) (seperti: nama pengguna akan selalu kurang dari 1000 karakter).


3

Untuk modul sederhana yang mungkin berakhir dengan toolkit, atau dalam jenis proyek sumber terbuka, Anda harus menguji sebanyak mungkin termasuk getter dan setter sepele. Hal yang ingin Anda ingat adalah bahwa menghasilkan unit test saat Anda menulis modul tertentu cukup sederhana dan mudah. Menambahkan getter dan setter adalah kode minimal dan dapat ditangani tanpa banyak berpikir. Namun, begitu kode Anda ditempatkan di sistem yang lebih besar, upaya ekstra ini dapat melindungi Anda terhadap perubahan dalam sistem yang mendasarinya, seperti mengetikkan perubahan di kelas dasar. Menguji segala sesuatu adalah cara terbaik untuk memiliki regresi yang lengkap.


2

Tidak ada ruginya menulis unit test untuk getter dan setter Anda. Saat ini, mereka mungkin hanya melakukan field get / sets di bawah tenda, tetapi di masa depan Anda mungkin memiliki logika validasi, atau dependensi antar-properti yang perlu diuji. Lebih mudah untuk menulisnya sekarang saat Anda memikirkannya, lalu ingat untuk memperbaikinya jika saatnya tiba.


baik, jika getter / setter Anda memerlukan pengujian unit, harus ada beberapa logika yang terkait dengannya, sehingga itu berarti logika harus ditulis di dalamnya, jika mereka tidak memiliki logika, tidak ada pengujian unit yang perlu ditulis.
Pop Catalin

2
Maksudnya adalah bahwa logika dapat ditambahkan kepada mereka nanti.
LegendLength

2

secara umum, ketika suatu metode hanya didefinisikan untuk nilai-nilai tertentu, uji untuk nilai-nilai di dan di luar perbatasan apa yang dapat diterima. Dengan kata lain, pastikan metode Anda melakukan apa yang seharusnya dilakukan, tetapi tidak lebih . Ini penting, karena ketika Anda akan gagal, Anda ingin gagal lebih awal.

Dalam hierarki warisan, pastikan untuk menguji kepatuhan LSP .

Menguji getter dan setter default sepertinya tidak terlalu berguna bagi saya, kecuali jika Anda berencana untuk melakukan validasi nanti.


2

baik jika Anda pikir itu bisa pecah, tulis tes untuk itu. Saya biasanya tidak menguji setter / pengambil, tetapi katakanlah Anda membuat satu untuk User.Name, yang menggabungkan nama depan dan belakang, saya akan menulis tes jadi jika seseorang mengubah urutan untuk nama belakang dan nama depan, setidaknya dia akan tahu dia mengubah sesuatu yang diuji.


2

Jawaban kanonik adalah "uji apa pun yang mungkin bisa rusak." Jika Anda yakin properti tidak akan pecah, jangan mengujinya.

Dan sekali ada sesuatu yang ditemukan rusak (Anda menemukan bug), jelas itu berarti Anda perlu mengujinya. Tulis tes untuk mereproduksi bug, lihat gagal, lalu perbaiki bug, lalu tonton tes lulus.


1

Seperti yang saya pahami unit test dalam konteks pengembangan gesit, Mike, ya, Anda perlu menguji getter dan setter (dengan asumsi mereka terlihat secara publik). Seluruh konsep pengujian unit adalah untuk menguji unit perangkat lunak, yang merupakan kelas dalam hal ini, sebagai kotak hitam . Karena getter dan setter terlihat secara eksternal, Anda perlu mengujinya bersama dengan Otentikasi dan Simpan.


1

Jika metode Otentikasi dan Simpan menggunakan properti, maka pengujian Anda secara tidak langsung akan menyentuh properti. Selama properti hanya menyediakan akses ke data, maka pengujian eksplisit tidak diperlukan (kecuali Anda akan mendapatkan cakupan 100%).


1

Saya akan menguji getter dan setter Anda. Bergantung pada siapa yang menulis kode, beberapa orang mengubah arti metode pengambil / penyetel. Saya telah melihat inisialisasi variabel dan validasi lainnya sebagai bagian dari metode pengambil. Untuk menguji hal semacam ini, Anda ingin tes unit mencakup kode itu secara eksplisit.


1

Secara pribadi saya akan "menguji apa pun yang dapat merusak" dan pengambil sederhana (atau properti otomatis yang lebih baik) tidak akan rusak. Saya tidak pernah mengalami kegagalan pernyataan pengembalian yang sederhana dan karenanya tidak pernah memiliki tes untuk mereka. Jika getter memiliki perhitungan di dalamnya atau beberapa bentuk pernyataan lainnya, saya pasti akan menambahkan tes untuk mereka.

Secara pribadi saya menggunakan Moq sebagai kerangka objek tiruan dan kemudian memverifikasi bahwa objek saya memanggil objek di sekitarnya seperti yang seharusnya.


1

Anda harus mencakup pelaksanaan setiap metode kelas dengan UT dan memeriksa nilai pengembalian metode. Ini termasuk getter dan setter, terutama dalam hal anggota (properti) adalah kelas kompleks, yang membutuhkan alokasi memori besar selama inisialisasi mereka. Panggil penyetel dengan string yang sangat besar misalnya (atau sesuatu dengan simbol yunani) dan periksa hasilnya benar (tidak terpotong, pengkodean baik dll)

Dalam hal bilangan bulat sederhana yang juga berlaku - apa yang terjadi jika Anda melewati panjang bukannya bilangan bulat? Itulah alasan Anda menulis UT untuk :)


1

Saya tidak akan menguji pengaturan properti yang sebenarnya. Saya akan lebih peduli tentang bagaimana properti-properti itu dihuni oleh konsumen, dan dengan apa mereka mengisinya. Dengan pengujian apa pun, Anda harus menimbang risiko dengan waktu / biaya pengujian.


1

Anda harus menguji "setiap blok kode non-sepele" menggunakan tes unit sejauh mungkin.

Jika properti Anda sepele dan tidak mungkin seseorang akan memperkenalkan bug di dalamnya, maka aman untuk tidak mengujinya.

Metode Otentikasi () dan Simpan () Anda tampak seperti kandidat yang baik untuk pengujian.


1

Idealnya, Anda akan melakukan tes unit saat Anda menulis kelas. Beginilah seharusnya Anda melakukannya saat menggunakan Test Driven Development. Anda menambahkan tes saat Anda menerapkan setiap titik fungsi, memastikan bahwa Anda menutupi kasus tepi dengan tes juga.

Menulis tes sesudahnya jauh lebih menyakitkan, tetapi bisa dilakukan.

Inilah yang akan saya lakukan di posisi Anda:

  1. Tulis satu set tes dasar yang menguji fungsi inti.
  2. Dapatkan NCover dan jalankan di tes Anda. Cakupan tes Anda mungkin sekitar 50% pada saat ini.
  3. Terus tambahkan tes yang menutupi casing tepi Anda hingga Anda mendapatkan cakupan sekitar 80% -90%

Ini akan memberi Anda set unit kerja yang bagus yang akan bertindak sebagai penyangga yang baik terhadap regresi.

Satu-satunya masalah dengan pendekatan ini adalah bahwa kode harus dirancang agar dapat diuji dengan cara ini. Jika Anda membuat kesalahan pemasangan sejak dini, Anda tidak akan bisa mendapatkan cakupan tinggi dengan sangat mudah.

Inilah sebabnya mengapa sangat penting untuk menulis tes sebelum Anda menulis kode. Ini memaksa Anda untuk menulis kode yang longgar digabungkan.


1

Jangan menguji kode yang jelas bekerja (boilerplate). Jadi jika setter dan getter Anda hanya "propertyvalue = value" dan "return propertyvalue", tidak masuk akal untuk mengujinya.


1

Bahkan mendapatkan / mengatur dapat memiliki konsekuensi ganjil, tergantung pada bagaimana mereka telah diterapkan, sehingga mereka harus diperlakukan sebagai metode.

Setiap pengujian ini perlu menentukan set parameter untuk properti, mendefinisikan properti yang dapat diterima dan tidak dapat diterima untuk memastikan panggilan kembali / gagal dengan cara yang diharapkan.

Anda juga perlu mengetahui adanya masalah keamanan, sebagai contoh injeksi SQL, dan uji untuk ini.

Jadi ya, Anda perlu khawatir tentang pengujian properti.


1

Saya percaya itu konyol untuk menguji getter & setter ketika mereka hanya melakukan operasi sederhana. Secara pribadi saya tidak menulis tes unit yang rumit untuk mencakup pola penggunaan apa pun. Saya mencoba menulis cukup tes untuk memastikan saya telah menangani perilaku eksekusi normal dan sebanyak kasus kesalahan yang dapat saya pikirkan. Saya akan menulis lebih banyak unit test sebagai tanggapan terhadap laporan bug. Saya menggunakan unit test untuk memastikan kode memenuhi persyaratan dan untuk membuat modifikasi di masa depan lebih mudah. Saya merasa jauh lebih bersedia untuk mengubah kode ketika saya tahu bahwa jika saya memecahkan sesuatu tes akan gagal.


1

Saya akan menulis tes untuk apa pun yang Anda tulis kode untuk itu dapat diuji di luar antarmuka GUI.

Biasanya, setiap logika yang saya tulis yang memiliki logika bisnis apa pun saya tempatkan di dalam lapisan lain atau lapisan logika bisnis.

Kemudian menulis tes untuk apa pun yang melakukan sesuatu mudah dilakukan.

Lulus pertama, tulis uji unit untuk setiap metode publik di "Lapisan Logika Bisnis" Anda.

Jika saya memiliki kelas seperti ini:

   public class AccountService
    {
        public void DebitAccount(int accountNumber, double amount)
        {

        }

        public void CreditAccount(int accountNumber, double amount)
        {

        }

        public void CloseAccount(int accountNumber)
        {

        }
    }

Hal pertama yang akan saya lakukan sebelum saya menulis kode mengetahui bahwa saya memiliki tindakan untuk melakukan ini adalah mulai menulis tes unit.

   [TestFixture]
    public class AccountServiceTests
    {
        [Test]
        public void DebitAccountTest()
        {

        }

        [Test]
        public void CreditAccountTest()
        {

        }

        [Test]
        public void CloseAccountTest()
        {

        }
    }

Tulis tes Anda untuk memvalidasi kode yang Anda tulis untuk melakukan sesuatu. Jika Anda mengulangi kumpulan hal-hal, dan mengubah sesuatu tentang masing-masing, tulis tes yang melakukan hal yang sama dan Tegaskan yang sebenarnya terjadi.

Ada banyak pendekatan lain yang dapat Anda ambil, yaitu Behavoir Driven Development (BDD), yang lebih terlibat dan bukan tempat yang bagus untuk memulai dengan keterampilan pengujian unit Anda.

Jadi, moral dari cerita ini adalah, uji apa pun yang melakukan apa pun yang Anda khawatirkan, pertahankan unit ini menguji hal-hal tertentu yang berukuran kecil, banyak tes yang baik.

Simpan logika bisnis Anda di luar lapisan Antarmuka Pengguna sehingga Anda dapat dengan mudah menulis tes untuk mereka, dan Anda akan menjadi baik.

Saya merekomendasikan TestDriven.Net atau ReSharper karena keduanya mudah diintegrasikan ke dalam Visual Studio.


1

Saya akan merekomendasikan menulis beberapa tes untuk metode Otentikasi dan Simpan Anda. Selain kasus sukses (di mana semua parameter disediakan, semuanya dieja dengan benar, dll), ada baiknya untuk menguji berbagai kasus kegagalan (parameter salah atau hilang, koneksi basis data tidak tersedia jika berlaku, dll). Saya merekomendasikan Pengujian Unit Pragmatis dalam C # dengan NUnit sebagai referensi.

Seperti yang telah dinyatakan orang lain, pengujian unit untuk getter dan setter berlebihan, kecuali ada logika kondisional pada getter dan setter Anda.


1

Meskipun dimungkinkan untuk menebak dengan benar di mana kode Anda perlu pengujian, saya biasanya berpikir Anda perlu metrik untuk mendukung dugaan ini. Pengujian unit dalam pandangan saya sejalan dengan metrik cakupan kode.

Kode dengan banyak tes tetapi cakupan kecil belum diuji dengan baik. Yang mengatakan, kode dengan cakupan 100% tetapi tidak menguji kasus-kasus batas dan kesalahan juga tidak bagus.

Anda ingin keseimbangan antara cakupan tinggi (minimum 90%) dan data input variabel.

Ingatlah untuk menguji "sampah masuk"!

Selain itu, unit-test bukanlah unit-test kecuali memeriksa kegagalan. Tes unit yang tidak memiliki konfirmasi atau ditandai dengan pengecualian yang diketahui hanya akan menguji bahwa kode tidak mati saat dijalankan!

Anda perlu merancang tes Anda sehingga selalu melaporkan kegagalan atau data yang tidak diharapkan / tidak diinginkan!


1

Itu membuat kode kita lebih baik ... titik!

Satu hal yang para pengembang perangkat lunak kita lupakan ketika melakukan pengembangan yang didorong oleh tes adalah tujuan di balik tindakan kita. Jika tes unit sedang ditulis setelah kode produksi sudah ada, nilai tes turun (tetapi tidak sepenuhnya hilang).

Dalam semangat sejati untuk pengujian unit, tes-tes ini terutama tidak ada di sana untuk "menguji" lebih banyak kode kita; atau untuk mendapatkan cakupan kode 90% -100% lebih baik. Ini semua adalah manfaat tambahan menulis tes pertama. Imbalan besarnya adalah bahwa kode produksi kami berakhir ditulis lebih baik karena proses alami TDD.

Untuk membantu mengomunikasikan ide ini dengan lebih baik, berikut ini mungkin membantu dalam membaca:

The Flawed Theory of Unit
Tess Tujuan Pengembangan Perangkat Lunak

Jika kita merasa bahwa tindakan menulis lebih banyak unit test adalah apa yang membantu kita mendapatkan produk yang lebih berkualitas, maka kita mungkin menderita Cargo Cult dari Test Driven Development.


Saya tidak setuju dengan pernyataan bahwa unit test tidak memiliki nilai setelah kode produksi sudah ada. Pernyataan seperti itu tidak menjelaskan kegunaannya dalam mereplikasi kondisi kesalahan yang ditemukan dalam produksi, atau dalam memahami kode yang diwarisi dari pengembang atau tim sebelumnya.
Scott Lawrence

Saya mungkin menemukan salah. Saya tidak bermaksud bahwa unit test tidak memiliki nilai setelah kode produksi ada. Namun, nilainya turun. Manfaat terbesar untuk pengujian unit berasal dari sihir bawaan yang terjadi ketika kita membiarkan mereka mendorong pengembangan produksi kita.
Scott Saad
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.