There is a discussion in the spanish TDD group about whether it is good or bad, when you have a stub object, to return a different value depending on the input arguments of the method. I don't think it's the right thing to do because, normally, when a stub object cares about the input arguments in its method calls it's because it should not be a stub object, it should be a mock object. Let me explain it with an example:
The payment gateway is a stub that returns true when user_has_funds is called with an input argument of 50.
If we look carefully at the test, what we are really doing is testing more than one behavior. First, we're asserting that a user can buy stuff if she has sufficient funds. Second, we are expecting that the payment gateway is called with the right amount.
So, if it is an expectation, why don't we use a mock instead of a stub? We're mixing the concepts of mock and stub and, as a consequence, we're testing more than one thing.We're breaking the single responsibility principle.
Steve Freeman and Nat Pryce, authors of the great Growing objects oriented software, guided by tests, recommend to follow a simple rule of thumb, "specify exactly what you want to happen and no more". If we listen to them (and we should!), those are the resulting tests:
The first test specifies the relationship between the order and the payment gateway (The message protocol). It uses a mock object to replace the gateway payment object and it expects a call at user_has_funds method with the order amount as an input argument. We want to know that the payment gateway is going to be called with the right amount, so we are interested in its input argument (which is right when mocking). The second one specifies the behavior of the order when the user has funds, and I don't really care about how the order interacts with the payment gateway. I just want to know that the user has sufficient funds. That's why, in this case, we use a stub.
What I like about the new tests is that, if we change the order behavior by adding some taxes to the product price, the second test is not going to break (we still confirm the order if the payment gateway says that the user has funds, nothing has changed in that specification). Only the first one would be red (and for the right cause, we've changed exactly that specification).
What do you think?
PS: I know that, in RSpec:mocks, stub() is an alias for mock() and I don't like it very much :P
Mostrando entradas con la etiqueta RSpec. Mostrar todas las entradas
Mostrando entradas con la etiqueta RSpec. Mostrar todas las entradas
miércoles, 9 de febrero de 2011
lunes, 29 de noviembre de 2010
Eden por dentro
Hoy he empezado mi internship en Eden y tengo que deciros que esto es la caña. He conocido a Chris, Todd, Spencer, Juliet y Aimee y son todos muy simpáticos y muy amables. Entre Chris y Aimee me han explicado lo que es Eden y me han pasado su "código de valores" (A ver si mañana os blogueo algo). Sinceramente, es una empresa espectacular. No se muy bien como explicarlo, pero escucharles contar como sienten la empresa y verlos en acción con sus clientes deja bien claro que su máximo interes es hacer que las personas se superen. Es muy inspirador.
Aimee y Steve iban a ser los encargados de darme caña estos primeros días, pero Steve (al que conocí en la Software Craftsmanship y al que todavía debo una cerveza) está enfermo y le ha tocado a Aimee lidiar conmigo :) Lo primero que hemos hecho Aimee y yo ha sido modificar la web de Eden. Supongo que la mayoría ya os habréis dado cuenta del cambio :P El proceso entero ha sido muy sencillo. El código está en github y el deploy se hace con un comando. A prueba de plagelaos :)
Más tarde, Aimee me ha encargado (ha petición de enrique vía email) una tarea algo más compleja. Me ha pedido que realice una implementación de un servidor web que cumpla la rfc2616 :) Además, tendré que hacer una exposición sobre el tema el próximo viernes... Por supuesto, hay que desarrollarlo usando TDD (Con Cucumber y RSpec). Para añadir algo de dificultad al ejercicio, me he propuesto hacerlo en Ruby y utilizando el Vim (bueno, el MacVim, que es algo más amigable) ¿Qué puede salir mal? Pues nada, porque hemos venido a aprender y a mejorar, y eso no se consigue dentro de tu zona de confort. Hay que tirarse a la piscina.
Por si os interesa el código lo estoy dejando en github, aunque estos próximos días os iré contando mis dudas y las soluciones. De momento, hoy he aprendido a lanzar todos los specs de mi proyecto a la vez :P Os cuento como lo he hecho. Me he creado un fichero spec_helper.rb en el que he metido todos los ficheros con specs como require. Después lo único que hago es ruby spec_helper.rb y automagicamente se ejecutan todos los tests. Supongo que habrá alguna forma más sencilla de hacerlo ¿Me la contáis? Tampoco me importaría mirar un poco como funciona autotest...
No quería terminar sin agradeceros a todos los ánimos que me estáis dando :D ¡Muchas gracias!
Por cierto, creo que en Madrid ha nevado hoy ¿no? Aquí ha salido el sol por la mañana :) La vida puede ser maravillosa, que decía aquel.
Saludos del "Lucky Bastard" :P
PD: Me dejo muchas cosas en el tintero (Todd explicándome que si tengo algún problema no dude en hablar con él, Spencer recogiéndome en el B&B para llevarme a Eden, el bollo que me ha comprado Juliet, las cañas que nos hemos tomado al salir con los chicos de la empresa cliente a la que están ayudando de la que no recuerdo el nombre ahora, etc). Todo genial.
Aimee y Steve iban a ser los encargados de darme caña estos primeros días, pero Steve (al que conocí en la Software Craftsmanship y al que todavía debo una cerveza) está enfermo y le ha tocado a Aimee lidiar conmigo :) Lo primero que hemos hecho Aimee y yo ha sido modificar la web de Eden. Supongo que la mayoría ya os habréis dado cuenta del cambio :P El proceso entero ha sido muy sencillo. El código está en github y el deploy se hace con un comando. A prueba de plagelaos :)
Más tarde, Aimee me ha encargado (ha petición de enrique vía email) una tarea algo más compleja. Me ha pedido que realice una implementación de un servidor web que cumpla la rfc2616 :) Además, tendré que hacer una exposición sobre el tema el próximo viernes... Por supuesto, hay que desarrollarlo usando TDD (Con Cucumber y RSpec). Para añadir algo de dificultad al ejercicio, me he propuesto hacerlo en Ruby y utilizando el Vim (bueno, el MacVim, que es algo más amigable) ¿Qué puede salir mal? Pues nada, porque hemos venido a aprender y a mejorar, y eso no se consigue dentro de tu zona de confort. Hay que tirarse a la piscina.
Por si os interesa el código lo estoy dejando en github, aunque estos próximos días os iré contando mis dudas y las soluciones. De momento, hoy he aprendido a lanzar todos los specs de mi proyecto a la vez :P Os cuento como lo he hecho. Me he creado un fichero spec_helper.rb en el que he metido todos los ficheros con specs como require. Después lo único que hago es ruby spec_helper.rb y automagicamente se ejecutan todos los tests. Supongo que habrá alguna forma más sencilla de hacerlo ¿Me la contáis? Tampoco me importaría mirar un poco como funciona autotest...
No quería terminar sin agradeceros a todos los ánimos que me estáis dando :D ¡Muchas gracias!
Por cierto, creo que en Madrid ha nevado hoy ¿no? Aquí ha salido el sol por la mañana :) La vida puede ser maravillosa, que decía aquel.
Saludos del "Lucky Bastard" :P
PD: Me dejo muchas cosas en el tintero (Todd explicándome que si tengo algún problema no dude en hablar con él, Spencer recogiéndome en el B&B para llevarme a Eden, el bollo que me ha comprado Juliet, las cañas que nos hemos tomado al salir con los chicos de la empresa cliente a la que están ayudando de la que no recuerdo el nombre ahora, etc). Todo genial.
Suscribirse a:
Entradas (Atom)