Test ayarınız gerçek testten daha büyük olduğunda
TL;DR: Yalnızca kısmen kullanılan şişman bir kurulum, testlerinizi daha bağlantılı ve anlamak daha zor hale getirir.
TL;DR: Yalnızca kısmen kullanılan şişman bir kurulum, testlerinizi daha bağlantılı ve anlamak daha zor hale getirir.
Sorunlar
- Çiftleşme
- okunabilirlik
- Kaçırılan süreler
- Yanlış Anlatım Konteyneri
- Gizli Test Bağımlılıkları
- Daha zor bakım
- Brittle test odası
- Bağımlılıkları karıştırmak
- Yavaş yürütme
- Yanlış kontekst
Çözümler
- odaklı kurulum yöntemleri oluşturmak
- Test-specific fixtures uygulama
- Minimum ayarları oluşturun
- Fabrika test yöntemlerinin uygulanması
Geri Dönüşüm ️
https://hackernoon.com/improving-the-code-one-line-at-a-time
https://maximilianocontieri.com/refactoring-011-replace-comments-with-tests
bağlamı
Testler yazdığınızda, çeşitli nesneleri başlatan büyük bir kurulum yöntemi oluşturabilirsiniz.
Sadece bir test tüm bu nesneleri kullanırken diğer testler sadece küçük bir alt set kullanırsa, gereksiz bir üst başlık oluşturursunuz.
Bu yaygın sorun, gelecekteki testlerin kapsamlı bir kurulum gerektirebileceğini tahmin ettiğinizde veya gerçekte neye ihtiyacınız olduğunu değerlendirmeden mevcut bir kurulumda ekleyeceğinizde meydana gelir.
Testler, alakası olmayan bağlamları içerdiğinden anlamak daha zordur ve kullanılmayan nesneleri başlatmanız nedeniyle gerçekleştirmek daha yavaşdır.
Kod örnekleri
Yanlış
public class TVSeriesTest {
private MovieSeries theEthernaut;
private List<Character> characters;
private List<Episode> episodes;
private User user;
private UserPreferences preferences;
private RatingSystem ratingSystem;
private StreamingService streamingService;
private List<Review> 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", "john@example.com", 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<Episode> 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());
}
}
Doğru
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<Episode> 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", "john@example.com", 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);
}
}
Keşifler
- [x] Yarı otomatik
Bu kokuyu, kurulum yöntemlerinde ayarlanmış olanları her testte kullanılanlarla karşılaştırarak tespit edebilirsiniz.
Başlatılan nesnelerin% 50'inden daha azını kullanan testleri arayın.
Kod kapsamı araçları, belirli testler tarafından kurulumun hangi bölümlerinin yürütülmediğini göstererek kullanılmayan kurulum nesnelerini tanımlamaya yardımcı olabilir.
Farklı bağlamlar oluşturmak için kurulumda koşullar yazmayı bulursanız, bunun yerine bir test özel kurulumuna ihtiyacınız olduğunu açık bir işarettir.
Güncel ️
- test etmek
Seviye
- [x] Ortaçağ
Neden bu kadar önemli ️
Her test, belirli bir gerçek dünya senaryosunu yansıtmalıdır.
Bükülmüş kurulumlar bu netliği kırar, neyi test ettiğini görmek zordur ve hataların olasılığını arttırır.
Bu kırıkbişeylerTestleri anlamak daha zor hale getirir, çünkü kurulumun hangi yönlerinin test için kritik olduğunu ve hangilerin sadece gürültü olduğunu belirleyemezsiniz.
Bir test başarısız olduğunda, başarısızlığa ilişkin olmayan bağımlılıkları araştırmak için daha fazla zaman harcayacaksınız.
Test daha kırılgan hale gelir, çünkü bu nesneler kurulum sürecine katılırsa kullanılmayan nesnelerin değişiklikleri hala testleri kırabilir.
Bu nesil
AI kod jeneratörleri genellikle tüm olası senaryoları kapsaymaya çalışan kapsamlı test ekipmanları oluştururken bu kokuyu yaratır.
Tamamlanmayı odaklanmaktan önceliklendirirler, bu da bireysel testler için gerekenden daha fazla nesneyi başlatan şişmiş kurulum yöntemlerine yol açar.
Keşfedilecek Yerler
AI, bu kokuyu "Test ayarımı sadece her test için gerekenleri içermek için optimize edin" gibi basit talimatlarla tespit edebilir.
Modern AI araçları, kurulum kodunu test yönteminin kullanımıyla karşılaştırabilir ve ortak kurulumları test spesifik kurulumlardan ayırarak hedefli refactoringlar önerebilir.
Bunu deneyin!
Unutmayın: AI Asistanları Birçok Hata Yapar
Önerilen prompt: Testleri ve kurulumları kırın
Önerilen prompt: Testleri ve kurulumları kırın
Without Proper Instructions |
With Specific Instructions |
---|---|
Sonuçlar
Sadece birkaç test tarafından gerekli olan nesneleri başlatan aşırı yüklü test ayarları, test paketinizi anlamak ve sürdürmek için daha zor hale getirir.
Her bir testin ihtiyaç duyduğu şeyi içeren odaklı kurulumlar oluşturduğunuzda testlerin netliğini, hızını ve güvenilirliğini arttırırsınız.
Testlerin örneklerle davranışları belgelemek amacıyla yapıldığını unutmayın veYorumları değiştir.
Çok fazla alakası olmayan bağlam, bu örnekleri daha az okunabilir hale getirir. Temiz testler gereksiz rahatsızlıklar olmadan net bir hikaye anlatır.
İlişkiler
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxv
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xi-sit35t1
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xxiii
https://hackernoon.com/how-to-find-the-stinky-parts-of-your-code-part-xli
Daha fazla bilgi
Disclaimer
Kokularım benimgörüşü.
Kredi
FotoğrafçılıkMarsilya SimoniBenimUnsplash Hakkında
Bir testten önce çok fazla yapıyı oluşturmanız gerekiyorsa, belki de çok fazla katmanla test ediyorsunuzdur.
Bir testten önce çok fazla yapıyı oluşturmanız gerekiyorsa, belki de çok fazla katmanla test ediyorsunuzdur.
James Gölü
Bu makale CodeSmell serisinin bir parçasıdır.