PDR'nin cevabına daha pratik bir yaklaşım getirmek . TDD tamamen testten ziyade yazılım tasarımı ile ilgilidir. İşinizi ilerlerken doğrulamak için birim testleri kullanırsınız.
Bu yüzden, bir birim test seviyesinde, birimleri tamamen belirleyici bir şekilde test edilebilecek şekilde tasarlamanız gerekir. Bunu, üniteyi belirsiz kılan (rasgele sayı üreteci gibi) yapan herhangi bir şeyi alıp soyutlandırarak yapabilirsiniz. Diyelim ki bir hamlenin iyi olup olmadığına karar veren saf bir yöntemimiz var:
class Decider {
public boolean decide(float input, float risk) {
float inputRand = Math.random();
if (inputRand > input) {
float riskRand = Math.random();
}
return false;
}
}
// The usage:
Decider d = new Decider();
d.decide(0.1337f, 0.1337f);
Bu yöntemi test etmek çok zordur ve birim testlerde gerçekten doğrulayabileceğiniz tek şey sınırlarıdır ... ancak bu sınırlara ulaşmak için çok fazla deneme gerektirir. Bunun yerine, bir arabirim ve işlevselliği saran somut bir sınıf oluşturarak rastgele parçayı soyutlayalım:
public interface IRandom {
public float random();
}
public class ConcreteRandom implements IRandom {
public float random() {
return Math.random();
}
}
Decider
Sınıf artık yani Arayüz onun soyutlama yoluyla somut sınıfını kullanması gerekir. Bu şekilde yapmanın bağımlılık enjeksiyonu denir (aşağıdaki örnek yapıcı enjeksiyonunun bir örneğidir, ancak bunu bir ayarlayıcı ile de yapabilirsiniz):
class Decider {
IRandom irandom;
public Decider(IRandom irandom) { // constructor injection
this.irandom = irandom;
}
public boolean decide(float input, float risk) {
float inputRand = irandom.random();
if (inputRand > input) {
float riskRand = irandom.random();
}
return false;
}
}
// The usage:
Decider d = new Decider(new ConcreteRandom);
d.decide(0.1337f, 0.1337f);
Bu kod kodunun neden gerekli olduğunu kendinize sorabilirsiniz. Peki, yeni başlayanlar için, şimdi s "kontratını" Decider
takip eden bir bağımlılığa sahip olduğundan, algoritmanın rastgele bölümünün davranışını alay edebilirsiniz IRandom
. Bunun için alaycı bir çerçeve kullanabilirsiniz, ancak bu örnek kendinizi kodlamak için yeterince basittir:
class MockedRandom() implements IRandom {
public List<Float> floats = new ArrayList<Float>();
int pos;
public void addFloat(float f) {
floats.add(f);
}
public float random() {
float out = floats.get(pos);
if (pos != floats.size()) {
pos++;
}
return out;
}
}
En iyi yanı, bunun "gerçek" somut uygulamanın tamamen yerini alabilmesidir. Kodun test edilmesi kolaylaşır:
@Before void setUp() {
MockedRandom mRandom = new MockedRandom();
Decider decider = new Decider(mRandom);
}
@Test
public void testDecisionWithLowInput_ShouldGiveFalse() {
mRandom.addFloat(0f);
assertFalse(decider.decide(0.1337f, 0.1337f));
}
@Test
public void testDecisionWithHighInputRandButLowRiskRand_ShouldGiveFalse() {
mRandom.addFloat(1f);
mRandom.addFloat(0f);
assertFalse(decider.decide(0.1337f, 0.1337f));
}
@Test
public void testDecisionWithHighInputRandAndHighRiskRand_ShouldGiveTrue() {
mRandom.addFloat(1f);
mRandom.addFloat(1f);
assertTrue(decider.decide(0.1337f, 0.1337f));
}
Umarım bu, uygulamanızı nasıl tasarlayacağınız konusunda fikir verir, böylece permütasyonlar zorlanabilir, böylece tüm uç durumları ve neyi test edemezsiniz.