SCRUM. У кого на работе считают, что используют?
Получается "вначале тест" не следует понимать буквально.
Желательно понимать буквально. Но мы живем в реальном мире :D
В идеальном мире сначала пишется тест Sum_2plus2_4 (), а функция Sum выглядит так:
public int Sum(int v1, int v2) { return 4; }
Потом добавляется тест Sum_2plus3_5() и функция Sum видоизменяется до:
public int Sum(int v1, int v2) { return v1 + v2; }
В каких-то случаях, как например в этом примере, можно опустить некоторые шаги, а в других случаях лучше не отходить от канона.
Вот только не доходит чем это мне поможет сделать более лучшую реализацию.
Простой пример: у тебя есть некий енкодер, который получает строку, шифрует, скажем DES'ом, ее и отправляет по COM-порту.
И вот этот энкодер написан:
public class SomeEncoder { public void EncodeAndSend (string message) { using (DESCryptoServiceProvider cryptic = new DESCryptoServiceProvider()) { cryptic.Key = ASCIIEncoding.ASCII.GetBytes("ABCDEFGH"); cryptic.IV = ASCIIEncoding.ASCII.GetBytes("ABCDEFGH"); using (MemoryStream ms = new MemoryStream()) { using (CryptoStream crStream = new CryptoStream(ms, cryptic.CreateEncryptor(), CryptoStreamMode.Write)) { byte[] data = ASCIIEncoding.ASCII.GetBytes("Hello World!"); crStream.Write(data, 0, data.Length); SerialPort comPort = new SerialPort("COM1"); comPort.Write(Encoding.Default.GetString(ms.ToArray())); } } } } }
Теперь надо протестировать эту функцию... В том виде, как она есть сейчас протестировать ее юнит-тестом невозможно.
Чтобы функция была тестируемая нам надо заменить обращение к шифрованию и к ком порту интерфейсами.
Делаем интерфейсы:
public interface ICrypt { byte [] Crypt (string message, string key); } public interface ITransport { void Send (byte [] data); }
Теперь изменяем наш класс:
public class SomeEncoder { private ICrypt Crypt { get; set;} private ITransport Transport{ get; set;} public SomeEncoder (ICrypt crypt, ITransport transport) { Crypt = crypt; Transport = transport; } public void EncodeAndSend (string message) { byte [] cryptData = Crypt.Crypt ("Hello World!", "ABCDEFGH"); Transport.Send (cryptData); } }
После таких изменений функция поддается тестированию.
Стал ли наш код лучше? Однозначно да! Во-первых, он стал тестируем. Во-вторых, он сразу стал расширяемым, т.к. мы теперь не завязаны ни на алгоритм шифрования, ни на COM порт.
И все это благодаря юнит-тестированию :)
И что говорит теория относительно данного вызова функции?
А что тут говорить? Это обычный юнит-тест на поведение при пограничных значениях. Так сказать тест на отказоустойчивость.