Pengujian unit
luar batas kelas itu sendiri, dan terutama tidak boleh menyeberangi batas proses/jaringan itu karena dapat memasukkan masalah kinerja yang tidak dapat diterima terhadap kumpulan pengujian unit. Melanggar batas-batas unit tersebut mengubah pengujian unit menjadi pengujian integrasi, dan ketika kasus uji gagal, kurang jelas komponen mana yang menyebabkan kegagalan.
Sebaliknya, pengembang perangkat lunak harus membuat antarmuka abstrak untuk permohonan (query) basis data, dan kemudian menerapkan antarmuka tersebut dengan objek pura-pura mereka sendiri. Dengan mengabstraksi keterkaitan yang diperlukan ini dari kode, unit independen dapat menjadi lebih benar-benar teruji dibandingkan yang sebelumnya mungkin tercapai. Hasilnya adalah unit yang lebih berkualitas tinggi dan juga lebih mudah dipelihara.
Pengujian unit terparameterisasi (PUT, parameterized unit tests) adalah uji yang menerima parameter. Tidak seperti pengujian unit tradisional yang biasanya merupakan metode tertutup, PUT menerima parameter mana pun. PUT telah didukung oleh TestNG, JUnit dan berbagai kerangka kerja pengujian.NET. Parameter yang cocok untuk pengujian unit dapat diberikan secara manual atau dalam beberapa kasus dihasilkan secara otomatis
oleh kerangka kerja pengujian. Alat-alat pengujian seperti QuickCheck ada untuk menghasilkan masukan pengujian untuk PUT.
Pengujian tidak akan menangkap setiap kesalahan dalam program, karena proses ini tidak dapat mengevaluasi setiap jalur eksekusi kecuali pada program yang paling sepele. Masalah ini merupakan superset dari masalah penghentian (halting problem), yang tergolong undecidable. Hal yang sama berlaku untuk pengujian unit.
Selain itu, pengujian unit secara definisi hanya menguji fungsi dari unit itu sendiri. Oleh karena itu, pengujian tidak akan menangkap galat integrasi atau galat aras sistem yang lebih luas (seperti fungsi-fungsi yang dilakukan melintasi beberapa unit, atau wilayah uji non-fungsional, seperti kinerja). Pengujian unit harus dilakukan bersama-sama dengan kegiatan
pengujian perangkat lunak lainnya, karena pengujian unit hanya dapat menunjukkan ada atau tidak adanya kesalahan tertentu, dan tidak dapat membuktikan unit bersih dari kesalahan. Untuk menjamin perilaku yang benar untuk setiap jalur eksekusi dan untuk setiap kemungkinan masukan, dan untuk memastikan tidak adanya kesalahan, diperlukan teknik yang
lain. Teknik ini adalah penerapan metode formal untuk membuktikan bahwa komponen perangkat lunak tidak memiliki perilaku tak terduga.
Hierarki pengujian unit yang rumit tidak sama dengan pengujian integrasi. Integrasi dengan unit pinggiran (periferal) harus dimasukkan dalam pengujian integrasi, tapi tidak diperlukan dalam pengujian unit. Pengujian integrasi biasanya masih sangat bergantung pada pengujian secara manual oleh manusia; Pengujian tingkat tinggi atau pengujian ruang lingkup global bisa jadi sukar untuk diotomatisasi, sehingga pengujian manual sering lebih cepat dan lebih murah.
Pengujian perangkat lunak adalah masalah kombinatorial. Misalnya, setiap pernyataan keputusan boolean membutuhkan setidaknya dua uji: satu dengan hasil yang "benar" dan satu dengan hasil "salah". Akibatnya, untuk setiap baris kode yang ditulis, pemrogram sering membutuhkan 3 sampai 5 baris kode uji. hal Ini jelas membutuhkan waktu dan
investasi yang mungkin tidak layak. Ada juga banyak masalah yang tidak dapat dengan mudah diuji sama sekali- misalnya masalah yang nondeterministik atau melibatkan beberapa utas ("thread"). Selain itu, kode untuk pengujian unit bisa jadi memiliki kekutu sama banyaknya dengan kode program yang diujinya. Fred Brooks dalam "The Mythical Man-Month" menyebutkan: "Jangan pernah pergi
ke laut dengan dua kronometer; bawa satu atau tiga." Artinya, jika dua kronometer bertentangan, bagaimana Anda tahu mana yang benar?
Tantangan lain yang terkait dengan menulis pengujian unit adalah kesulitan menciptakan uji yang realistis dan berguna. Kondisi awal yang relevan sangat perlu diciptakan agar aplikasi yang diuji berperilaku seperti bagian dari sistem yang lengkap. Jika kondisi awal ini tidak diatur dengan benar, pengujian tidak akan menggerakkan kode dalam konteks realistis, yang akan mengurangi nilai dan akurasi dari hasil pengujian unit.
Untuk mendapatkan manfaat yang diharapkan dari pengujian unit, disiplin ketat diperlukan sepanjang proses pengembangan perangkat lunak. Penting untuk mencatat dengan hati-hati tidak hanya uji yang telah dilakukan, tetapi juga dari semua perubahan yang telah dilakukan ke kode sumber unit tersebut atau unit lain dalam perangkat lunak. Penggunaansistem pengontrol versi adalah penting. Jika
versi yang lebih baru dari suatu unit gagal melalui uji tertentu yang sebelumnya berhasil dilewati, perangkat lunak pengontrol versi dapat memberikan daftar perubahan kode sumber yang telah diterapkan (jika ada) terhadap unit sejak saat itu.
Hal penting pula untuk menerapkan proses yang berkelanjutan untuk memastikan bahwa kegagalan kasus uji ditinjau setiap hari dan segera diatasi. Jika proses tersebut tidak dilaksanakan dan tidak tertanam ke dalam alur kerja tim, aplikasi akan berkembang liar, tidak lagi selaras dengan kumpulan pengujian unit, meningkatkan positif palsu dan mengurangi keefektifan kumpulan pengujian.
Pengujian unit perangkat lunak sistem benam (embedded system) menghadirkan tantangan unik: karena perangkat lunak tersebut dikembangkan pada landasan yang berbeda dari landasan yang nantinya akan menjalankannya, Anda tidak dapat dengan mudah menjalankan program pengujian pada lingkungan pelaksanaan (deployment) sebenarnya, seperti yang mungkin dilakukan dengan program desktop.
Pengujian unit adalah dasar dari pemrograman ekstrem, yang bergantung pada kerangka kerja pengujian unit terotomatisasi. Kerangka kerja pengujian unit terotomatisasi ini mungkin berasal dari pihak ketiga, misalnya, xUnit, atau diciptakan dalam kelompok pengembangan perangkat lunak itu sendiri.
Pemrograman ekstrem menggunakan penciptaan pengujian unit untuk pengembangan digerakkan pengujian. Pengembang menulis pengujian unit yang mengekspos baik persyaratan atau cacat suatu perangkat lunak. Uji ini akan gagal karena salah satu persyaratan belum diimplementasikan, atau karena sengaja memperlihatkan cacat dalam kode yang sudah ada. Kemudian, pengembang menulis kode sederhana untuk agar unit lulus uji tersebut, bersama dengan uji yang lainnya.
Sebagian besar kode dalam sistem melewati pengujian unit, tetapi belum tentu menguji semua jalur dalam kode. Pemrograman ekstrem memandatkan strategi "menguji segala sesuatu yang mungkin gagal", dan menghindari metode tradisional "menguji setiap jalur eksekusi". Hal ini menyebabkan pengembang untuk menciptakan uji yang lebih sedikit dari metode klasik, tapi ini tidak
benar-benar masalah. Metode klasik pun jarang pernah diikuti secara ketat sehingga tidak semua jalur eksekusi telah diuji secara menyeluruh. Pemrograman ekstrem hanya mengakui bahwa pengujian jarang dilakukan secara menyeluruh (karena sering terlalu mahal dan memakan waktu) dan memberikan panduan tentang bagaimana memusatkan sumber daya yang terbatas secara efektif.
Kode pengujian ini dianggap artefak proyek kelas satu, dalam artian dipertahankan pada kualitas yang sama dengan kode implementasi, dengan menghapus semua duplikasi kode. Pengembang merilis pengujian unit ke repositori kode bersama-sama dengan kode yang diujinya. Pengujian unit yang menyeluruh dari pemrograman ekstrem memungkinkan manfaat yang disebutkan di
atas, seperti pengembangan kode yang dan refaktorisasi lebih sederhana dan lebih meyakinkan, integrasi kode yang disederhanakan, dokumentasi yang akurat, dan desain yang lebih modular. Pengujian unit ini juga terus berjalan sebagai bentuk dari uji regresi.
Pengujian unit juga penting untuk konsep desain emergen. Karena desain emergen sangat tergantung pada refaktorisasi, pengujian unit merupakan satu komponen tidak terpisahkan.