Saat pengaturan tes Anda lebih besar dari tes yang sebenarnya
Tl; dr: pengaturan membengkak yang hanya digunakan sebagian membuat tes Anda lebih digabungkan dan lebih sulit untuk dipahami.
Masalah π
- Kopel
- Keterbacaan
- Waktu eksekusi yang terbuang
- Konteks pengaturan yang menyesatkan
- Ketergantungan tes tersembunyi
- Pemeliharaan yang lebih sulit
- Suite uji rapuh
- Ketergantungan yang membingungkan
- Eksekusi lebih lambat
- Konteks yang menyesatkan
Solusi π
- Buat metode pengaturan yang terfokus
- Terapkan perlengkapan khusus tes
- Buat pengaturan minimal
- Menerapkan metode pabrik pengujian
Refactorings βοΈ
https://hackernoon.com/improving-the-code-one-line-at-e-time
https://maximilianocontieri.com/refactoring-011-replace-comments-with-tests
Konteks π¬
Saat Anda menulis tes, Anda dapat membuat metode pengaturan besar yang menginisialisasi berbagai objek.
Jika hanya satu tes menggunakan semua objek ini sementara tes lain hanya menggunakan subset kecil, Anda membuat overhead yang tidak perlu.
Masalah umum ini terjadi ketika Anda mengharapkan bahwa tes di masa depan mungkin memerlukan pengaturan yang luas, atau ketika Anda terus menambah pengaturan yang ada tanpa mengevaluasi apa yang benar -benar dibutuhkan.
Tes lebih sulit untuk dipahami karena mengandung konteks yang tidak relevan, dan lebih lambat untuk dieksekusi karena Anda menginisialisasi objek yang tidak digunakan.
Kode Sampel π
Salah β
public class TVSeriesTest {
private MovieSeries theEthernaut;
private List characters;
private List episodes;
private User user;
private UserPreferences preferences;
private RatingSystem ratingSystem;
private StreamingService streamingService;
private List reviews;
@BeforeEach
public void setUp() {
// Create a complex movie series with many characters
characters = new ArrayList();
characters.add(new Character("Juan Salvo", "Richard Darin"));
characters.add(new Character("Helen", "Carla Peterson"));
characters.add(new Character("Favalli", "Cesar Troncoso"));
// Create episodes
episodes = new ArrayList();
episodes.add(
new Episode("The Snow", 2025, 121));
episodes.add(
new Episode("The Hands Strikes Back", 2027, 124));
// Create user with preferences
preferences = new UserPreferences();
preferences.setPreferredGenre("Science Fiction");
preferences.setPreferredLanguage("English");
preferences.setSubtitlesEnabled(true);
user = new User("JohnDoe", "[emailΒ protected]", preferences);
// Create rating system with reviews
ratingSystem = new RatingSystem(10);
reviews = new ArrayList();
reviews.add(
new Review(user, "The Snow", 9, "Classic!"));
reviews.add(
new Review(user, "The Hands Strikes Back", 10, "Best one!"));
ratingSystem.addReviews(reviews);
// Create streaming service
streamingService = new StreamingService("Netflix");
streamingService.addMovieSeries("The Eternaut");
// Finally create the movie series with all components
theEthernaut =
new TVSeries("The Ethernaut", characters, episodes);
theEthernaut.setRatingSystem(ratingSystem);
theEthernaut.setAvailableOn(streamingService);
// This method is too long. That is another smell
}
@Test
public void testTVSeriesRecommendation() {
// This test uses almost everything from the setup
RecommendationEngine engine = new RecommendationEngine();
List recommended =
engine.recommendations(user, theEternaut);
assertEquals(2, recommended.size());
assertEquals("The Hands Strikes Back",
recommended.get(0).title());
// You are testing the recomendation Engine
// This is not this object's responsibility
}
@Test
public void testEpisodeCount() {
// This test only needs the episodes count
assertEquals(2, theEthernaut.episodes().size());
}
@Test
public void testCharacterLookup() {
// This test only needs the characters
// And not the rest of the setup
Character juan = theEternaut.findCharacterByName("Juan Salvo");
assertNotNull(juan);
assertEquals("Juan Salvo", juan.actor());
}
}
Benar π
public class TVSeriesTest {
// No shared setup
@Test
public void testRecommendation() {
// Create only what's needed for this specific test
// And move this test with the behavior
TVSeries theEternaut = createTheEternautSeries();
User homer = createUserWithPreferences();
addReviewsForUser(theEternaut, homer);
RecommendationEngine engine = new RecommendationEngine();
List recommended =
engine.recommendations(homer, theEternaut);
assertEquals(2, recommended.size());
assertEquals("The Hands Strikes Back",
recommended.get(0).title());
}
@Test
public void testEpisodeCount() {
// Only create what's needed - just the episodes
TVSeries theEternaut = new TVSeries("The Ethernaut");
theEternaut.addEpisode(
new Episode("The Snow", 2025, 121));
theEternaut.addEpisode(
new Episode("The Hands Strikes Back", 2027, 124));
assertEquals(2, theEternaut.episodes().size());
}
@Test
public void testCharacterLookup() {
// Only create what's needed - just the characters
TVSeries theEternaut = new TVSeries("The Eternaut");
theEternaut.addCharacter(
new Character("Juan Salvo", "Richard Darin"));
theEternaut.addCharacter(
new Character("Helen", "Carla Peterson"));
Character juan = theEternaut.findCharacterByName("Juan Salvo");
assertNotNull(juan);
assertEquals("Richard Darin", juan.actor());
}
// Helper methods for specific test setup needs
private TVSeries createTheEternautTVSeries() {
TVSeries series = new TVSeries("The Eternaut");
series.addEpisode(
new Episode("The Snow", 2025, 121));
series.addEpisode(
new Episode("The Hands Strikes Back", 2027, 124));
return series;
}
private User createUserWithPreferences() {
UserPreferences preferences = new UserPreferences();
preferences.setPreferredGenre("Science Fiction");
preferences.setPreferredLanguage("English");
return new User("JohnDoe", "[emailΒ protected]", preferences);
}
private void addReviewsForUser(TVSeries series, User user) {
RatingSystem ratingSystem = new RatingSystem(10);
ratingSystem.addReview(
new Review(user, "The Snow", 9, "Classic!"));
ratingSystem.addReview(
new Review(user, "The Hands Strikes Back", 10, "Best one!"));
series.setRatingSystem(ratingSystem);
}
}
Deteksi π
Anda dapat mendeteksi bau ini dengan membandingkan apa yang diatur dalam metode pengaturan terhadap apa yang digunakan dalam setiap tes.
Cari tes yang menggunakan kurang dari 50% objek yang diinisialisasi.
Alat cakupan kode dapat membantu mengidentifikasi objek pengaturan yang tidak digunakan dengan menunjukkan bagian mana dari pengaturan yang tidak dijalankan dengan tes tertentu.
Jika Anda menemukan diri Anda menulis kondisionalitas dalam pengaturan untuk membuat konteks yang berbeda, itu adalah tanda yang jelas Anda memerlukan pengaturan khusus tes.
Level π
Mengapa Bibe itu Penting πΊοΈ
Setiap tes harus mencerminkan skenario dunia nyata tertentu.
Pengaturan membengkak mematahkan kejelasan ini, membuatnya sulit untuk melihat apa yang sedang diuji dan meningkatkan kemungkinan kesalahan.
Bijeksi yang rusak ini membuat tes lebih sulit dipahami karena Anda tidak dapat menentukan aspek pengaturan mana yang penting untuk tes dan mana yang hanya noise.
Ketika tes gagal, Anda akan menghabiskan lebih banyak waktu untuk menyelidiki dependensi yang mungkin tidak relevan dengan kegagalan.
Tes menjadi lebih rapuh karena perubahan pada objek yang tidak digunakan masih dapat merusak tes jika objek tersebut berpartisipasi dalam proses pengaturan.
AI Generasi π€
Generator kode AI sering membuat bau ini ketika mereka menghasilkan perlengkapan uji komprehensif yang mencoba untuk mencakup semua skenario yang mungkin.
Mereka memprioritaskan kelengkapan tentang fokus, menghasilkan metode pengaturan yang membengkak yang menginisialisasi lebih banyak objek daripada yang dibutuhkan untuk tes individu.
Deteksi AI π₯
AI dapat mendeteksi bau ini dengan instruksi sederhana seperti “Optimalkan pengaturan tes saya hanya untuk memasukkan apa yang diperlukan untuk setiap tes.”
Alat AI modern dapat membandingkan kode pengaturan dengan penggunaan metode uji dan menyarankan refactorings yang ditargetkan, memisahkan pengaturan bersama dari pengaturan khusus tes.
Coba mereka! π
Ingat: asisten ai membuat banyak kesalahan
Prompt Disarankan: Hancurkan tes dan pengaturan
Kesimpulan π
Pengaturan tes yang kelebihan beban yang menginisialisasi objek yang hanya diperlukan oleh beberapa tes membuat suite tes Anda lebih sulit untuk dipahami dan dipelihara.
Saat Anda membuat pengaturan terfokus yang hanya berisi apa yang dibutuhkan setiap tes, Anda meningkatkan kejelasan, kecepatan, dan keandalan tes Anda.
Ingatlah bahwa tes bertujuan untuk mendokumentasikan perilaku melalui contoh dan mengganti komentar.
Konteks yang terlalu tidak relevan membuat contoh -contoh itu kurang mudah dibaca. Tes bersih menceritakan kisah yang jelas tanpa gangguan yang tidak perlu.
Hubungan π©ββ€οΈβπβπ¨
https://hackernoon.com/how-to-find-the-stinky-part-of-your-code-part-xxv
https://hackernoon.com/how-to-find-the-stinky-part-of-your-code-part-xi-sit35t1
https://hackernoon.com/how-to-find-the-stinky-part-of-your-code-part-xxiii
https://hackernoon.com/how-to-find-the-stinky-part-of-your-code-part-xli
Informasi lebih lanjut π
Penafian π
Bau kode adalah pendapat saya.
Kredit π
Foto oleh Marcin Simonides di Unsplash
Jika Anda harus membuat banyak struktur sebelum tes, mungkin Anda menguji terlalu banyak lapisan
James Shore
Artikel ini adalah bagian dari seri CodeSmell.