Writing Testable Code in C# Chapter 1 – Constructors

C# has many toys when it comes to constructors. Classes can have many types of constructors;

  • Default constructor
  • Parameterized constructor
  • Private constructor
  • Static constructor
  • Copy constructor

This topic is not about getting to know C# constructors but how to use them to write testable code. Now it is time to go check these constructor types if you don’t know these.

Basically a C# class has a default constructor generated by the compiler if you don’t provide one. You can have many parameterized constructors like function overloads and parameterless constructor in the same class. Copy constructors are used to pass the same type to another instance as a constructor parameter. Private constructors only exist in classes that you cannot create instances. Static constructors are the only interesting ones in the lot, they don’t take access modifiers, there can be only 1 static constructor to a class, they can’t have parameters, they can reside with default constructors.

I can hear you saying “I thought we were testing specs and functionality who cares about constructors?” You are right. When we do unit testing we are using a fundamental pattern called AAA;

  • Arrange
    In this step, we are setting up our test environment. Maybe creating some variables, some classes, if necessary some mock objects.
  • Act
    In this step, we are executing the test by calling a function most of the time.
  • Assert
    In this step, we are checking if the output or the state changes that is caused by the Act satisfies our expectations.

So the Arrange step is directly relevant with constructors because we are creating instances. Passing constructor parameters. Acknowledging this and some simple rules can help you writing testable code. Even if you are planning to add tests later, your design and implementation should allow testing the behaviour easily. Here are the examples you should avoid;


Using “new” Keyword In Your Constructors


Lets start from the most common and easy to solve code smell;

We have a PathFinder class that finds texts / paths in a large xml. We decided to put the instantiation of the XMLReader into PathFinder. We want to test the Find logic.

As you see below we can test the Find logic perfectly. Everything is great.


Actually No! To test Find logic we instantiated a “new XMLReader()” in our PathFinder constructor. Everytime we try to test the Find logic we have to create this class instance too. Maybe today XMLReader doesn’t do much in it’s own constructor but somebody might change its behaviour and it may take longer. Even worse, it might be throwing an exception and that is another behaviour you should consider in your tests.

Also now you are stuck with XMLReader in PathFinder. You can’t load xml from another source or with an other implementation.

Unit testing implies testing of a Unit as the name implies. We are testing two units at this case.

ProTip: Unit tests should be so fast, and repeatable. You should be able to run them every time you change a bit of code. This way when you break something  you can see what is failing and go fix it quickly rather than searching where you have failed in a long code or a large project. It’s all about isolating the functionality that is being tested. There are tools for every language running tests in background while you are coding and show you an interface.

How to make this code testable;

Polymorphism and Dependency Injection (DI) are your tools here. I know every unit test / tdd blog starts with them but be patient, I will show you more details in the following sections.


Created an IDocumentSource interface and changed the behaviour of XMLReader according to this. Now I don’t even need to have XMLReader class to test PathFinder.


Changed the PathFinder constructor. Now instead of creating an instance it accepts an injection as constructor parameter.

ProTip: You guessed it right. This is Dependency Injection (DI). It is not something complicated, we just pass documentSource as a parameter.

Also we use polymorphism; we use IDocumentSource interface as parameter instead of the concrete class. Now we can pass anything that satisfies that contract. We can pass mocks, stubs, fakes or the actual concrete class. Really helps us to isolate the functionality that we test.


Updated the test so that we return a dummy document using a Mock object instead of loading from large XML with the concrete XMLReader class.

Setup the mock, so that we are sure in PathFinder we call the LoadDocument and get the Document after it is loaded.

Now we have an extra line for actually reading document. We moved this behaviour to an upper level in callstack. This means our code is more flexible now. We can have one PathFinder and read many times.

Yes we have a little bit more code here but you will see the advantage. Note that this was for sake of providing an example. In real life the components are bigger and the amount of code is likely to be the same because the setup of the test is straightforward.

Now we have set the basics, let’s move forward with the next example.


Constructors Calling Static Methods


In your project you decided to create some static fields. When used for these reasons it makes testing hard..

  • singletons
  • shared resources like in-memory caching
  • utility classes

When you depend on these excessively, these classes become a burden when your project grows. It is ok to use Extension or Conversion methods as long as they don’t have side effects and are composed. You can test those individually. Other than that using static variables represent global state and it is really hard to test. That is a very common code-smell and you should be careful with those.

ProTip: For most of the hidden states in large classes, we extract those into other meaningful classes. This way we can test them separately also we can use those to have mocks/stubs to test the main classes functionality. It is a technique that we use a lot when we refactor to more testable code.

Let’s say we have a Counter class and another Class1 calling this Counter method in its constructor.


It looks simple. Every Class1 that we create gets a new Index number starting with 1.

Lets try to unit test this behaviour.


Yes, as you have guessed we got errors.



Remember these TDD / unit test rules

  • Tests should be fast
  • Tests should be repeatable at any time
  • Tests shouldn’t have state so that we can call them parallel (this is also true for test fixtures)
  • Tests should not depend on each other to run
  • Tests should be as simple as possible, preferably asserting one thing

In this example our tests can’t run in parallel and they are not repeatable. Should we implement a Reset method in our Counter class just to test it? What if in the future we run our tests on a fast Bamboo server in parallel with 50 more tests addressing this Counter behaviour? Between Reset and Increment methods you can have parallel tests Increments. Then you have wobbly test results. So the answer is No!

What is the testable approach here?

In our Class1 specific unit tests, we are testing the behaviour of Class1 only. Knowing what to test and what is not in the test scope is really important. In our example, calling Increment and checking the Index is 1 but the Index is not important for us. Currently we are doing these tests for just code coverage. The main target should be checking if the Increment method of the Counter called is in our constructor. In the future when somebody deletes this code accidently, our test should fail.

If we change the Static class to non-static, now we can inject a copy of Counter class into Class1. Yes, I break things by converting a static class to non-static. But other classes were dependent to the implementation of Counter. Now they don’t care if the injected reference is defined static somewhere upper tier in architecture. You can now decide how to instantiate Counter. Maybe when your project gets larger, you decide to have an IoC container. C# has abundant list of IoC containers. Then get rid of static copy of Counter and have it as a singleton. You have many options. Do you recognize how writing testable code changed your architecture in a better way?


 Now we can mock the injected ICounter and test if it’s called in the constructor.


We did it! We could use any number instead of 1, 2 and assert it because we are independent of Counter implementation. Remember we are testing the unit behaviour of Class1 here. If somebody decides to change Class1’s constructor in the future, these tests will assert the usage is still there.

Pro Tip: We have extended the testing strategy here. Sometimes we don’t even need to use assert directly in our test AAA structures. You don’t have to. When you get used to unit testing, you will see that AAA structure blends into SetUps, TearDowns, explicit Mock behaviours. You can see the MockBehavior.Strict and VerifyAll() in the TearDown. That is already an assertion.

Now our tests pass.



Constructors Having Business Logic


I have read somewhere “Do not put any business logic or initialization code into constructors, only set parameters”. That looks very strict right? Lets elaborate on this a little bit.

There is no “right” way to do things in C#. There are many debates of constructors having logic. You can write business decisions to your constructors. Some of the publicly recognized C# patterns are executing decisions in their constructors. But even if they are proven to be good, that doesn’t mean they are testable.

Also initialization may still have logic. Maybe in your constructor you try to connect to a database. At first this design seems error free but that is an external domain to your application scope and it may throw errors. You would like to catch those and maybe throw something else, or handle gracefully or retry connecting. But testing these are also hard if they are in constructors.

ProTip: I simply recognized recently, constructors are not named code blocks. I mean you can’t name them properly. A constructor doing xml file loading should be renamed as “LoadXmlFile” or a constructor checking database connection should be named as CheckDbConnection right? That looks like a function then. Remember most of our work is naming things.

In this example we have a UserRepository with a constructor accepting cacheEnabled parameter as Boolean.


There is a business logic in constructor. If the cache is enabled, it decides to get all users from database into cache. If we connect this class to db and actually get users instead of returning null, it will work without any problems.

Lets plan some basic unit tests;

  • Test1 – If cache enabled, all users should be loaded into cache
  • Test2 – If cache disabled, there shouldn’t be a database call in constructor
  • Test3 – Get single user from cache
  • Test4 – Get single user from database

At this moment we can come up with more tests about this class’ behaviour. I tried to write two of the tests above with no avail;


At first test, there is no way to assert if GetAllUsersFromDb() is called or not. (Unless we add a public Boolean state as a backdoor and set it to true when it’s called or try to use reflection to check if this function is called)

At the second test, there is no way without connecting to db and getting all the users into cache. Remember what we said about tests being fast and repeatable. This test might take many seconds and also in a developer machine maybe it is impossible to cache because of large database.

With this approach if we had more constructor parameters, we wouldn’t know about the method calls and combinations inside the constructor. Even if we had the states for all the behaviour it is really hard to be sure. This code doesn’t look like testable and prone to future errors.


To test a closed system behaviour we need a defined cause and a measurable effect.

Let’s say we had a TV. We pressed the button on remote and TV is on now. In between these two observable things, IR message sent from remote, TV received it, then many parts in TV started working (power supply, tuner, logic board, lcd etc.) as a result we got the picture and sound. We don’t know what magic they are doing at the background. But we have a cause and an effect.

If we are testing the integration, we test all these aspects acting together end to end. For unit testing we need to isolate every unit and test them separately.

In our example, what happens the constructor throws an error? Or maybe we want to change the cache mechanism or database connectivity. How do we change these without breaking UserRepository unit business?

Here are some architectural problems;

  • We are violating SRP – Single Responsibility Principle. UserRepository shouldn’t run as a caching engine. This is not the business ruleset of UserRepository.
  • Cache mechanism is bound to Repository, there is no way to change without changing Repository.
  • There should be a way of separating database engine, cache engine, UserRepository wrapper and actual data.
  • We need isolation of all these separate responsibilities so that we can test them individually.

ProTip: Single Responsibility Principle is the “S” of the S.O.L.I.D principles. It means every module or class should have responsibility over single part of the functionality. As Robert C. Martin explains with reasoning: “A class should have only one reason to change”. All of the SOLID principles should be applied to our daily programming and testing practices.

As I stated at the beginning current implementation may run without problems. But even if this doesn’t look like a problem now, when your project gets larger, refactoring and changing the code that is not tested is risky. Unnecessary dependencies may block your future maintenance or increase your effort.

Here is how to make it testable;


A lot of change required for those architectural problems. Lets see what we have done;

  • Now database engine and cache engine are different classes. We don’t test them here so we don’t need to decide them now. We only need to focus on UserRepository behaviour.
  • UserRepository is merely a wrapper over database engine and cache engine. It’s code is now more simple. Remember to “Keep it simple, stupid”
  • No constructor code required. Cache engine data should be handled outside UserRepository domain. UserRepository is no responsible to fill the cache data.
  • We only set parameters in the constructor
  • Now our code is testable

Check the final UserRepository code here. It looks more complete. No gray areas, no comments, no todos, just simple. We don’t have to try to implement and decide large behaviour here so the changes we did drive us to a finished, working, testable code.

Protip: A factory pattern might be used here. A factory is a way to create the object without exposing the creation logic. It’s responsibility is to compose the object which supports Single Responsibility.

Here are some tests;


The details you should check here are;

  • We set the mock objects strictly. SetUp method runs before every test.
  • TearDown method runs after every test so we verify the mock behaviour. If any mock setup is not satisfied we get a warning.
  • Now it is easy to test that database not calling GetAllUsers on creation of UserRepository.
  • Also setting up mocks for database engine and cache engine is easy. For example; If cacheEngine.GetData method is not called during execution we get a mock exception and test fails.
  • AAA structure is blended into refactored test code. When we are Asserting we are also Acting (Assert … repo.GetUser)
  • There is no Assert line at the first test. Instead we verify GetAllUsers never called inside new UserRepository.



In this chapter we had a sneak peek of how to use constructors while writing testable code with C#.

In short, we should be careful with these code-smells;

  • Using “new” keyword in constructors
  • Calling static method in constructors
  • Setting hidden state in constructors (either static or not)
  • Logic code in constructors (also loops should be carefully investigated as code-smell)

What we can do about it;

  • Single Responsibility Principle rules should be checked. The code-smell mostly is at constructors
  • Separate and isolate those large classes so you have simpler, testable constructors
  • Think about if the class is a data class or a logic class. Separating those concerns will let you have clean constructors (and better design)
  • Move the hidden state to external classes
  • Dependency Injection is your friend
  • Keep It Simple Stupid (KISS)

These are general guidelines to follow at the beginning of your unit testing adventures. Of course, there are asides and exceptions. Remember there is not a single way to do things in C#.

You can download all the example code from this link.

Happy Coding 😊

Serkan Berksoy


I hereby thank my friend and colleauge Bas van der Linden for reviewing and making suggestions.

Writing Testable Code in C#

Testing is a method used for demonstrating that software satisfies its specification. It is a methodology to prevent faults being introduced when maintaining software. In the sixties this was done manually by e.g. labour-intensive debugging. Preventing faults in software with tests gained traction after 1990 historically.

As engineers we are always in search for better and more optimum solutions to our craftsmanship. while there are many alternative ideas around, the mainstream is having a testable software. Having unit tests is increasing the quality of software in many ways:

  • Helps us find the bugs earlier
  • Provides documentation on how the unit is intended to be used
  • Improves design
    • Simplifies maintaining and extending features
    • It forces your code to be more modular
  • Brings up clarity for developers, makes you really understand your code
  • Simplifies refactoring
  • Simplifies debugging and mostly removing the need of debugging
    (coding with relying on debugging is a bad habit)
  • Makes collaboration easier and more efficient
  • Removes the fear of change

It is also good for planning work if you can trust your code. Even better if you are developing TDD you are adding a lot of unit tests.

So now we got the basics. Having tests is good. We are telling every developer to test their code to increase quality. But the problem is that we don’t have a common definition of how to write testable code. Coming from more traditional coding styles and trying to adapt into unit testing is a delicate process. You need to change your mindset. It is challenging because some of these principles prohibit you using some of the language features.

In these series I will try to cover the principles of writing testable code with some examples.

You can download all the example code from this link.

Here are the chapters;

Test Driven Development – Test Yönelimli Geliştirme Üzerine

Test Driven Development, 11 yıldır yazılım yöneticiliği yapsam da son 7 yıldır öğrenip içselleştirip ekiplerimle uyguladığımız günlük metodolojilerden biri. Bugün biraz TDD hakkında teorik bilgi vermek istedim.

Peki nedir Test Driven Development? “Biz zaten testlerimizi yapıyoruz” dediğinizi duyar gibi oluyorum. Birçok danışmanlığını verdiğim şirkette programcılar “Ben kodumun gerekli yerlerine test yazıyorum, yani TDD biliyorum” diyor. Fakat TDD tamamen farklı bir yaklaşım.

TDD ne değildir;
TDD; isminde Test geçtiği halde yazılımınızı test etme metodolojisi değildir.
TDD; Unit Testing değildir. Bu kavramlar genelde karıştırılır.
TDD; bir mimari yaklaşımdır. Kodunuzu test etmeye değil testlerle geliştirmeye yarar.
TDD; bir vakit kaybı değildir. Yatırımınızı bugfix yapmaya, gereksiz iletişime, dokümantasyona ve güvensizliğe değil teste kaydırırsınız. Diğer Extreme Programming metodolojileri de vakit kaybı değildir. Şimdiye kadar irili ufaklı birçok ekipte ve projede büyük faydalarını gördük. Fakat bu da başka bir yazının konusu.

TDD ile yapmaya çalışıtığım tam olarak şudur; Değişik örnekler ekleyerek, mimaride yapacağım yeniliklerin, ekleyeceğim komplikasyonların bu örnekleri desteklediğini görmeye ve düzgün çalıştırdığını ispat etmeye çalışırım. Adım adım bu temellerin üzerine yeni senaryo örnekleri ekleyerek mimarimi ve kodumu geliştiririm.

Unit Testing ise tam olarak şudur; Biraz önce geliştirdiğim bir şeyin düzgün çalıştığından emin olmak istediğim için farklı örnekler eklerim. Bu örneklerle, yaptığım geliştirmemin en başta tasarladığım şekilde çalışıp çalışmadığını inceler, problem varsa tespit etmeye çalışırım.

TDD ile Unit Testing farklı düşünüş biçimleri, farklı bakış açılarıdır. TDD’de elinizdeki yazılımın sahip olmadığı bir özellikle ilgili gerçeklemesini istediğiniz testi ekler, öncelikle bunu yapmadığını ispat edersiniz. Daha sonra bu testi gerçekleyen en basit kodu yazar, testin geçtiğini ispat edersiniz. Unit Testing yaparken kodunuzu zaten yazmışsınızdır. “Acaba şu farklı parametreler / varyasyonlar için de çalışıyor mu?” yaklaşımı ile yaptığınız implementasyondan daha çok emin olmaya çalışırsınız.

Unit Testing kötüdür diye birşey söylenemez. Unit Testing, TDD gibi bir kod geliştirme aracıdır, kodunuza olan güvenimizi arttırmak için kullanırız. Her ikisine de ihtiyacımız var. Dahası, birçok projede ikisini de kullandığımız olmuştur.

Ne durumda hangisini yaptığınızın bilincinde olmanız yaptığınız işe hakimiyetinizi arttırır. Yapınıza ekleme mi yapıyorsunuz yoksa yaptığınızdan emin olmaya mı çalışıyorsunuz.

TDD ve BDD üzerine

3 yıldır TDD uyguluyoruz ve yakın zamanda BDD ile proje yapma fırsatı bulduk. TDD’yi J.B. Rainsberger’dan (kendisini çok sevdiğimiz Joe’dan) öğrendim, BDD’yi de daha sonra kendi çabamla öğrenip, deneyip ekibime anlattım.

İşe alım görüşmelerimde ve etrafımdaki yazılımcı arkadaşlarda gördüğüm fikir karmaşasına biraz daha açıklık getirmek üzere bu yazıyı hem yazılımcı hem yönetici penceresinden bakan bir açıyla yazma ihtiyacı hissettim.

Öncelikle şunu söylemeliyim ki; TDD, BDD, RDD, DDD ve yakın zamanda MDD ortaya çıkmadan da ekibimle gayet güzel iş yapıp teslim ediyorduk. Bug da çıkıyordu, requirement eksikleri de sonradan ortaya çıktığında dizayn bozukluğuna sebep oluyor ve patchy kod yazmamızı gerektiriyordu. Yazdığımız projeler yine 3 yıl sonra düzgün yönetilse bile (projesine göre değişir) ek yapıldıkça yavaş yavaş tekrar yazılma ihtiyacı gerektiren yöne doğru gidiyordu.

Yukarıdakileri kötü kod yazılıyor şeklinde yorumlamayın sakın, standartlarımıza bağlı, üzerinden düzenli codewalk yapılan, “temiz” kodlar yazdığımızdan emindik. Etrafımda çalışan arkadaşlar çok iyi yazılım mühendisleriydi.

TDD ile yazmaya başladığımızda hayatımızda ne değişti? Öncelike öğrenme sürecinde ciddi vakit kaybı yaşadık. Kafasında modeller tasarlayıp hemen uygulamaya geçen yazılımcıları dizginleyip, onlara işin nereye gideceğini bildikleri halde kafalarındaki bütünü bir yere not alıp, sonra tek tek, parça parça, ufaktan başlayıp test ederek o bütüne, testler başka yöne götürürse de o düzgün çalışan başka bütüne ulaşmayı öğrettik. Özellikle red-green-refactor yaparken refactor kısmında ne kadar iyi mühendislik, uzmanlık ve pattern bilgisi işin içine girerse o kadar düzgün bir yapıya ulaşılabileceğini gördük.

Öncelikle bize ters gelen bu yapı daha sonra alışkanlık haline geldi. Bu vaktin ve proje sürelerinin uzamasının bize nasıl bir dönüşü oldu derseniz en önemlileri;

– Artık kodun hiçbir parçasını değiştirmekten üşenmiyor, korkmuyoruz
– Deployment yapmaktan korkmuyoruz
– Proje bittiği noktadan itibaren yeni eklemeleri çok rahat yapabiliyoruz

Tabi yan getirileri de her şirketin (özellikle turnover yüksek olan şirketlerin) korktuğu, “bu kodun sahibi giderse ne yaparız”, “kod dokümanımız yeterli mi” sorularının cevabı olmuştu TDD. Testler, eğer düzgün isim verilirse kodun ne için yazıldığının dokümanı oluyor. Pair programming mantığı ise her adamın sürekli o koda ve yapıya alışık dublörüne şirket içinde acil durumlarda ulaşılabilir olmasını sağlıyor.

Fakat TDD’nin çözmediği, daha doğrusu çözmeyi hedeflemediği şeyler var. Koda aceleyle yeni gelen istekleri ekleyip mimari tasarımı hala bozabiliyorsunuz. Bu durumda projeleriniz yine değişme hızına göre 3-4 yıl içinde içine kod yazılmaz hale gelebilir. Yine requirement eksikleri oluşturduğunuz mimari tasarımdan başka birine kaymanızı gerektirebilir.

TDD’nin hedeflemediği asıl şey şirket ve yazılımcı kültürü, prensipleri. Eğer bu ikisinin prensipleri ve yaklaşımları yazılımın bakım ve ek istek uygulandığı aşamaları da düzgün yönetecek, bu aşamalarda da sadece ek yapılmayıp arada ciddi projeler çıkabileceği yönünde ise o zaman projeleriniz daha ayakları yere basar, olgun ilerleyebiliyor. Mimari tasarımaların değişmesi gerektiği noktada TDD’den sapmamayı kurum kültürü olarak benimseyebiliyorsanız o zaman başarılı olabiliyorsunuz.

Bu başarının tek yolu düzgün iç eğitimden ve yazılımcıların kendini ve projeyi rahat geliştirebilecekleri bir ortamdan geçiyor. Projelerde zaman-maliyet-kalite üçgeni dahilinde en optimumu yakalamak ve piyasa şartlarını kaçırmadan yazılımı teslim etmek için yazılımcılarınızın 10 kaplan gücünde olup altyapınızın ormandan daha düzenli olması gerekiyor.

Artık TDD yaptığımız ve yapmadığımız projelerin her dönem oluşan issue sayısını karşılaştırıp, başta harcadığımız vaktin kurumun itibarına nasıl yansıdığını görebiliyoruz.

BDD ise TDD’deki standardizasyondan türemiş daha sonuç odaklı bir yöntemdir. TDD yapan abilerimiz bir süre sonra sürekli AAA (Arrange-Act-Assert) veya Context-When-Then yaptıklarını görüp daha üst düzeyde bunu refactor ettiklerinde ve üzerine düzgün bir yapı yerleştirdiklerinde yaptıkları testlerin sistem davranışlarını test etmek olduğunu görmüşler. İşin içine iş ve ürün ekiplerini de katmanın ne kadar avantajlı olduğunu ve bunun üzerinden direkt unit-testlere geçilmesinin hız kazandıracağını görünce BDD, TDD gibi kuvvetli bir alternatif haline gelmiş.

BDD’de kullandığımız dil, en azından iş ekipleri açısından biraz ön çalışma gerektirir. Malesef her iş ekibi bu şekilde requirement yazmaya alışkın değildir. Bu yapının içinde olan analistler iş ekipleri ile yazılım ekipleri arasındaki köprüyü oluşturmaktadır. Eğer şirketinizde analist çalıştırmıyorsanız o zaman Behavior testlerini yazılımcıya (hani analyst-developer yazıyor ya kartvizitlerinizde) yazdırıp iş ekiplerine onaylatır, onları da bu yöntemle iş istemeye alıştırabilirsiniz.

BDD testleri yazılımcı tarafından yazıldığında TDD testlerine daha yakın, daha low level bir dil içerir. Sistemin daha alt birimlerini, unit’leri test etmeye daha yatkındır. StoryQ sitesinden alıntı yaptığım alttaki test iş birimi testlerine örnektir.

Story is Data Safety
In order to Keep my data safe
As a User
I want All credit card numbers to be encrypted
With scenario submitting shopping cart
Given I have typed my credit card number into the checkout page
When I click the Buy button                                     
And the browser posts my credit card number over the internet
Then the form should be posted over https

Aşağıdaki testler de bizim projemizden yazılımcının BDD testine örnek;

Story Add Customer To Advertisement Group Display
In order to Display
As an Admin User
I want To Display Customer Advertisment Group
With scenario Display Customer Advertisement Group befora add
Given Admin user loggedin
When AddCustomerToAdvertisementGroup called
And Querystring has CustomerID
And Method is get 
Then ViewName Should Be "Display"
And CustomerDisplayModel should be loaded

Farkındaysanız daha fazla teknik detay teste girmiş durumda. Eğer TDD ile geliştirme yapıyorsanız ve yöntemi doğru uyguluyorsanız, kodunuzun Test Coverage’ı hep 100% olacaktır. Hiç kontrol etmenize gerek yok. Fakat BDD ile test yazmak çok iyi ürün ve yazılım bilgisi gerektirir. Müşterinin hangi ekranda hangi model ile görüntüleceğini teknik olarak bilmeniz (veya test yazım aşamasında aşağı yukarı tahmin etmeniz) gerektiği gibi hangi bilgileri göstermeniz gerektiğini iş mantığı açısından bilmeniz gerekmektedir.

TDD ve BDD’de ortak olarak proje üzerinde karşınıza çıkan bug ve issue’ları da bunlarla ilgili yeni testler yazarak çözmelisiniz. Öncelikle eklemeyi yapıp sonra testleri tamamlamak yanlış olacaktır. Bu şekilde yöntemden uzaklaşmadan devam edebilirsiniz.

Başlarken farkında değildim fakat TDD ve BDD’nin avantajları, hangi kurumlar ve hangi tip ekip profilleri için olduğunu anlatmaya çalıştım. Bu yöntemlerden birine geçmek istiyorsanız ilgili testleri yazacak ve işin genelini yönetecek arkadaşları dikkatli seçmelisiniz.

Gelen soru ve isteklere göre yazının ikinci bölümünü yazmayı düşünebilirim.
Sevgiler, saygılar