Digamos que você desejasse testar seu aplicativo manualmente toda vez que o implantasse. Como você faria isso?
Bem, para começar, você pode fazer uma lista de todas as coisas que deseja testar, para não esquecer de testar algo mais tarde. Em seguida, você provavelmente escreveria as etapas de cada teste para garantir que você as executasse da mesma maneira todas as vezes. Se você não certificou-se de que o processo de teste usado fosse consistente, seus resultados não seriam consistentes.
Portanto, agora que você tem a lista de testes que precisa executar, abra o navegador, leia as etapas do primeiro teste, execute-as e anote o resultado. Você repetiria esse processo para cada teste em sua lista.
O número de testes que você realiza continuará a crescer à medida que seu aplicativo cresce e à medida que você encontra novos bugs. Obviamente, você estaria limitado a executar esses testes na velocidade humana, tornando-os bastante lentos.
A ironia aqui é que, ao percorrer mecanicamente uma lista de operações, você está computando. Você está fazendo isso muito mais devagar do que, digamos, um computador faria.
É por isso que, entre muitas outras boas razões, escrevemos testes de unidade: eles permitem que o computador faça a computação para que você não precise.
Posso executar um conjunto abrangente de testes de unidade com rapidez suficiente para usá-lo com frequência durante o desenvolvimento, não apenas uma vez por semana antes da implantação. Isso me permite detectar erros mais rapidamente, economizando tempo e dinheiro.
Posso até escrever testes que prevêem o comportamento do sistema e depois escrever esse comportamento (que eu já sei que está correto porque acabei de testá-lo), um processo conhecido como Desenvolvimento Orientado a Testes.