Unit Testing: "Ini bau kode jika Anda melakukan refactoring dan tidak ada kolaborator"?

9

Saya membaca The Art of Unit Testing oleh Roy Osherove. Saya di bagian 7.2. Menulis tes yang dapat dipertahankan di mana penulis memiliki catatan tentang bau kode ini:

CATATAN: Saat Anda menyatakan status internal agar terlihat oleh tes luar, apakah itu dapat dianggap sebagai bau kode (tanda bahwa ada sesuatu yang salah dalam desain atau logika kode)? Ini bukan bau kode ketika Anda refactoring untuk mengekspos kolaborator. Ini bau kode jika Anda melakukan refactoring dan tidak ada kolaborator (jadi Anda tidak perlu mematikan atau mengejek apa pun).

EDIT : Apa yang penulis maksudkan dengan "kolaborator" adalah dependensi. Beberapa contohnya untuk dependensi adalah kelas yang mengakses database atau yang mengakses sistem file OS. Di sinilah ia mendefinisikan rintisan dan mulai menggunakan kata kolaborator:

Sebuah rintisan adalah pengganti dikontrol untuk yang sudah ada ketergantungan (atau kolaborator ) dalam sistem.

Penulis tidak memiliki contoh bau kode ini dan saya mengalami kesulitan memahami / membayangkan seperti apa bentuknya. Dapatkah seseorang menjelaskan hal ini sedikit lebih banyak dan mungkin memberikan contoh nyata?

programmer
sumber
Saya pikir kebingungan di sini berasal dari kata "Collaborators". Saya harus mengakui bahwa saya juga tidak yakin apa yang ia maksudkan dalam konteks ini.
rossipedia
@Bryan Ross, saya memperbarui posting dengan cara penulis menggunakan kata "kolaborator". Terima kasih!
programmer

Jawaban:

3

Saya pikir inilah maksud penulis.

Dalam contoh kode saya, saya memiliki jendela waktu yang mengambil jumlah keluaran ditambah waktu mulai dan berhenti. Tujuannya adalah untuk menggambar jendela output dalam rentang waktu 24 jam. Kerutan ditambahkan ketika waktu mulai lebih besar dari waktu berhenti karena itu adalah jendela waktu yang membentang tengah malam.

Anda dapat menulis unit test yang sepenuhnya melatih objek tanpa mengekspos variabel pribadi. Bangku dan rentang waktu pribadi itu adalah kolaborator yang dia maksud ketika mengekspos internal untuk pengujian unit. Menurut buku itu, mengekspos internal itu TIDAK akan menjadi bau kode karena mereka adalah kolaborator.

Mengekspos ganda outputakan menjadi bau kode karena itu bukan kolaborator - ini adalah elemen yang secara eksplisit disembunyikan oleh kelas itu sendiri yang memiliki logika kondisional di dalamnya GetOutputuntuk menentukan apa yang harus dikembalikan.

Menggali ke dalam bools / rentang waktu akan membuat tes unit lebih komprehensif. Dia bilang ini bagus.
Menggali ke dalam double outputakan membutuhkan logika tambahan dalam unit test Anda yang mencerminkan apa yang GetOutputsedang dilakukan. Ini akan menjadi bau kode yang dia maksud.

TimeWindow kelas publik
{
  bool pribadi isConst;
  bool pribadi spansMidnight;
  TimeSpan start1 pribadi;
  TimeSpan stop1 pribadi;
  TimeSpan start2 pribadi;
  TimeSpan stop2 pribadi;
  output ganda pribadi;

  TimeWindow publik (double out, TimeSpan start, TimeSpan stop)
  {
    output = keluar;

    if (start == stop)
      isConst = true;
    lain jika (mulai> berhenti)
    {
      spansMidnight = true;
      start1 = tengah malam;
      stop1 = stop;
      start2 = mulai;
      stop2 = tengah malam;
    }
    lain 
    {
      start1 = mulai;
      stop1 = stop;
    }
  }

  GetOutput ganda publik (TimeSpan time)
  {
    // beberapa logika di sini tentang apa / bagaimana mengembalikannya
    ...
    hasil pengembalian;
  }

}

sumber
0

Katakanlah kita memiliki kelas domain, dan kelas domain ini memiliki pengetahuan langsung tentang lapisan persistensi menggunakan Repositori, yang digunakannya untuk mengekspos metode "Simpan" level-instance yang objek yang bekerja pada kelas domain dapat memanggil untuk bertahan perubahan dibuat tanpa perlu pengetahuan tentang mekanisme (apakah ini desain "baik" adalah diskusi untuk hari lain). Refactoring kelas untuk mengekspos Repositori ini sebagai argumen properti dan / atau konstruktor, sehingga memungkinkan Repositori tiruan untuk dilewati yang dapat memastikan panggilan yang tepat dibuat, biasanya merupakan hal yang baik tidak hanya untuk pengujian tetapi juga pemeliharaan umum.

Sekarang, ini menjadi kelas domain, ia memiliki data keadaan. Mari kita asumsikan sejenak bahwa salah satu properti stateful memiliki bidang dukungan, dan penguji properti menguji bahwa input baru valid berdasarkan yang saat ini (mungkin nilai baru tidak pernah bisa kurang dari yang lama). Anda perlu menguji validasi ini, tetapi Anda menemukan bahwa hal itu memerlukan akses ke bidang dukungan untuk menetapkan nilai awal yang kemudian akan Anda coba timpa. Ini harus menjadi bendera merah; jika tes membutuhkan akses ke bidang dukungan (yang merupakan implementasi detail; tidak ada konsumen harus pernahharus tahu ada di sana) untuk mendapatkan objek ke kondisi yang konsisten untuk pengujian, lalu bagaimana kode produksi mendapatkan objek yang konsisten? Jika ada metode untuk kode produksi untuk melakukan hal yang sama dengan tes Anda, maka tes mungkin harus meniru cara itu. Jika tidak ada cara yang valid untuk kode produksi untuk memasukkan objek ke keadaan ini, lalu mengapa Anda menguji skenario ini?

KeithS
sumber