TDD metodolojisi yukarıdan aşağıya uygulanabilir mi?


13

Metodoloji olan TDD'nin aşağıdaki durumu nasıl ele aldığından emin değilim. Diyelim ki Python'da mergesort algoritmasını uygulamak istiyorum. Yazarak başlarım

assert mergesort([]) === []

ve test başarısız olur

NameError: 'mergesort' adı tanımlanmadı

Sonra eklerim

def mergesort(a):
    return []

ve testim geçer. Sonra ekliyorum

assert mergesort[5] == 5

ve testim başarısız oluyor

AssertionError

hangi ile geçiyorum

def mergesort(a):
    if not a:
        return []
    else:
        return a

Sonra, ekliyorum

assert mergesort([10, 30, 20]) == [10, 20, 30]

ve şimdi bu geçişi yapmaya çalışmalıyım. Ben "mergesort algoritması biliyorum" bu yüzden yazmak:

def mergesort(a):
    if not a:
        return []
    else:
        left, right = a[:len(a)//2], a[len(a)//2:]
        return merge(mergesort(left)), mergesort(right))

Ve bu başarısız olur

NameError: 'birleştirme' adı tanımlanmadı

Şimdi soru şu. mergeTDD kullanarak uygulamaya nasıl başlayabilir ve uygulamaya başlayabilirim ? Yapamam gibi görünüyor çünkü bu "asılı" yerine getirilmemiş, başarısız testi mergesort, bitene kadar geçmeyecek var merge! Bu test takılırsa, TDD'yi asla gerçekten yapamam çünkü TDD yinelemelerimi oluştururken "yeşil" olmayacağım merge.

Aşağıdaki üç çirkin senaryoya takılı kaldım ve (1) TDD topluluğu bunlardan hangisini tercih ettiğini bilmek ister ya da (2) kaçırdığım başka bir yaklaşım var mı? Birkaç Bob Amca TD izlenimini izledim ve daha önce böyle bir vaka gördüğümü hatırlamıyorum!

İşte 3 durum:

  1. Birleştirme işlemini farklı bir dizinde farklı bir dizinde uygulayın.
  2. Yardımcı işlevi geliştirirken yeşil olma konusunda endişelenmeyin, sadece hangi testleri gerçekten geçmek istediğinizi manuel olarak takip edin .
  3. (! GASP) dışında açıklama veya satırları silmek mergesorto çağrı merge; sonra mergeişe koyulduktan sonra tekrar yerine koyun.

Bunların hepsi bana aptalca bakıyor (ya da buna yanlış mı bakıyorum?). Tercih edilen yaklaşımı bilen var mı?


2
TDD'nin amacının bir parçası, bir yazılım tasarımı oluşturmanıza yardımcı olmaktır. Bu tasarım sürecinin bir kısmı, istenen sonucu elde etmek için neyin gerekli olduğunu keşfetmektir. Durumunda mergesortzaten çok iyi tanımlanmış algoritma olduğundan, bu keşif süreci zorunlu değildir ve bu o zaman zaten birim testlerin bir dizi tasarım olarak bildiğimiz haritalama meselesi haline değildir. Muhtemelen, üst düzey testiniz test edilen yönteminizin sıralanmamış bir koleksiyonu kabul ettiğini ve sıralı bir koleksiyon döndürdüğünü
Robert Harvey

1
... Sonraki birim testleri yavaş yavaş a mergesort. Bunu yapmanın "doğru" yolunu arıyorsanız, mergesortalgoritmayı bir dizi birim sınamaya eşlemenizle ilgili doğru olmaktan başka bir yol yoktur ; yani mergesortaslında bir şeyin ne yaptığını yansıtmalıdırlar .
Robert Harvey

4
Tasarım sadece birim testlerden kendini büyütmez; bir mergesorttasarımın kırmızı-yeşil-refactor'dan doğal olarak ortaya çıkmasını bekliyorsanız , süreci mevcut bilginize göre yönlendirmezseniz bu gerçekleşmez mergesort.
Robert Harvey


1
TDD'de mergesadece "yeniden düzenleme" aşamasında icat edilmelidir. Bu mergeyöntemin testi mergesortgeçmeniz için tanıtılabileceğini görürseniz, ilk önce testlerinizi mergeyöntem olmadan geçirin . Ardından, mergeyöntemi tanıtarak uygulamanızı yeniden düzenleyin .
Fabio

Yanıtlar:


13

İşte seçeneklerinize bakmanın bazı alternatif yolları. Ama önce, TDD'nin kuralları, Bob Amca'dan benim vurgulayarak:

  1. Başarısız bir birim test geçişi yapmadığı sürece herhangi bir üretim kodu yazmanıza izin verilmez.
  2. Başarısız olmak için yeterli olandan daha fazla birim testi yazmanıza izin verilmez; ve derleme hataları hatalardır.
  3. Arızalı birim testini geçmek için yeterli olandan daha fazla üretim kodu yazmanıza izin verilmez .

Bu nedenle, kural numarası 3'ü okumanın bir yolu merge, testi geçmek için işleve ihtiyaç duymanızdır , böylece uygulayabilirsiniz - ancak yalnızca en temel biçiminde.

Alternatif olarak, birleştirme işlemini satır içine yazarak başlayıp, testin çalışmasını sağladıktan sonra bir işleve yeniden aktarabilirsiniz.

Başka bir yorum, birleştirme yazmanızdır, bir mergeoperasyona ihtiyacınız olduğunu bilirsiniz (yani, YAGNI değildir, bu da “yeterli” kuralın kısıtlamaya çalıştığı şeydir). Bu nedenle, birleştirme testleri ile başlamalısınız ve ancak daha sonra genel sıralama için testlere devam etmelisiniz.


Bunlar gerçekten iyi gözlemler. Daha önce satır içi ve çarpanlara ayırmayı düşünmüştüm, ama mergeşaşırtıcı derecede dağınık olduğu gibi , (hem bağımsız hem de bağımsız olarak) ayrı bir işlev olarak yapma fikri daha mantıklıydı. Bununla birlikte, bunu temel biçiminde satır içi yapma ve daha sonra mavi şapka aşamasında çarpanlara ayırma tarzı gerçekten doğru ve aradığım şey gibi görünüyor.
Ray Toal

@RayToal - Aslında mergesıralama yapmadan önce operasyonun tamamen test edilmesine (ve partitionoperasyonun ayrı testine ) yaklaşıyorum . Ortaya çıkan tasarımın iddia edilen faydaların yavaşça bilinen bir hedefe doğru çalışmasından kaynaklandığını düşünüyorum. MergeSort durumunda, ben yok (o zaman kabarcık sıralama ile bitireceğiz çünkü) hedefi genelde sıralama olduğunu düşünüyorum. Temel işlemleri biliyorsunuz, yani bu operasyonlara doğru çalışıyorsunuz; bu tür çoğunlukla sonradan düşünülen bir şeydir.
kdgregory

1
Dördüncü seçenek var. Geçiş mergeiçine fonksiyonu mergesortve davranışını alay. Sonra geri dönün ve mergeönce testi uygulayın . Delegeler harika ™.
RubberDuck

@RubberDuck Çekirdek etki alanının ayrılmaz bir parçasını alay etmek, özellikle programı çalıştırdığınızda ve alay ve birleştirme işlevi en az ayrıntıda farklılık gösterdiğinde bazı sorunlara yol açabilir. Sıralanacak listenin nereden geldiği gibi harici kaynaklarla çalıştığınız durumlarda böyle bir yaklaşım bırakılmalıdır.
16:49
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.