Pregunta

¿Es mejor agregar funciones que devuelvan el estado interno de un objeto para las pruebas unitarias, en lugar de hacer de la clase de prueba un amigo? - Especialmente, cuando no sirve de nada para las funciones, excepto el caso de las pruebas unitarias.

¿Fue útil?

Solución

Las pruebas unitarias deben 95% del tiempo solo probar la superficie expuesta públicamente de una clase. Si está probando algo bajo las portadas, son los detalles de implementación de pruebas, lo cual es inherentemente frágil, porque debería poder cambiar fácilmente la implementación y aún así que las pruebas funcionen. No solo es frágil, sino que también podría sentirse tentado a probar cosas que en realidad no son posibles en los escenarios de uso planificados, lo cual es una pérdida de tiempo.

Si el punto de los accesores que desea agregar es solo probar si la función tenía el efecto deseado, su diseño de clase puede violar otro principio, que es que una clase de estado de estado siempre debe dejar en claro en qué estado está, Si eso afecta lo que sucede cuando las personas interactúan con la clase. En ese caso, sería correcto proporcionar esos accesorios de solo lectura. Si no afecta el comportamiento de la clase, consulte mi parte anterior sobre los detalles de implementación.

Y como dijiste correctamente, abarrotar la superficie pública de una clase con cosas no utilizadas también es indeseable por sus propios motivos.

Si yo tenido Para elegir entre los accesorios y la amiga en su caso, elegiría el amigo, simplemente porque Posee tu prueba y pueda cambiarla en caso de apuro. No puede ser dueño del código por el payaso que encuentra una manera de usar sus accesorios adicionales, y luego estará atrapado.

Otros consejos

No estaré de acuerdo con la respuesta aceptada y, en cambio, recomendaré el uso de una clase de amigos.

Parte del estado que está probando probablemente sea específica para la implementación de su clase; Está probando detalles que otro código normalmente no conoce ni se preocupa y no debe confiar. Las funciones de los accesorios públicos hacen que estos detalles de implementación sean parte de la interfaz de la clase. Si el estado interno que está probando no forma parte de la interfaz prevista, no debe ser visible a través de funciones públicas. Desde un punto de vista purista, está atrapado entre dos respuestas incorrectas, ya que las clases de amigos también son técnicamente parte de la interfaz pública. En mi opinión, la pregunta es, ¿qué opción es menos probable que conduzca a malas opciones de codificación en el futuro? Ir con un conjunto de funciones de accesorios públicos dependientes de la implementación alentará inadvertidamente un modelo conceptual dependiente de la implementación de la clase, lo que lleva al uso dependiente de la implementación de la clase. Es menos probable que se abuse de una clase de un solo amigo, apropiadamente nombrado y documentado.

Si bien, en general, estoy totalmente de acuerdo con la recomendación de preferir las funciones de los accesorios sobre el acceso directo a las variables de los miembros, no estoy de acuerdo en que esta mejor práctica se aplique a las pruebas unitarias del estado interno dependiente de la implementación. Un punto medio razonable es usar privado Las funciones de accesorios a esas piezas de estado que le importará su prueba unitaria y serán lo suficientemente disciplinadas como para usar las funciones de accesorios en sus pruebas unitarias. Solo es mi opinión.

El uso de clases de amigos para pruebas unitarias es perfectamente legítima y le permite mantener la encapsulación. No debe modificar sus clases de interfaz pública simplemente para que la clase sea más comprobable. Piensa en ello de esta manera. ¿Qué pasa si compró una biblioteca FTP de terceros y está tratando de usarla y su interfaz pública está abarrotada de un montón de métodos que ni siquiera necesita conocer simplemente por las pruebas unitarias! Incluso modificar una interfaz protegida para compensar las pruebas unitarias es malo. Si estoy heredando de alguna clase, ¡no quiero tener que preocuparme por qué métodos son útiles para mí y cuáles solo están allí debido a las pruebas unitarias! El uso de clases de amigos para pruebas unitarias lo ayuda a mantener una interfaz de clase simple y más fácil de usar; ¡Ayuda a preservar la encapsulación y la abstracción!

He escuchado el argumento de que usar clases de amigos para pruebas unitarias es malo porque la clase bajo prueba no debe estar "estrechamente acoplada" con su clase de prueba y no debería "saber" nada sobre su clase de prueba. No compro esto. Es una sola línea agregada a la parte superior de la clase:

Clase de amigos MyClasStest;

¡Y ahora puedes probar tu clase de la forma que quieras!

Ahora estoy de acuerdo en que no debes usar una clase de amigo a menos que sea necesario. Si puede probar lo que necesita pruebas sin que sea un amigo, por supuesto. Pero si la vida se vuelve difícil y el uso de una clase de amigo hace que la vida sea fácil nuevamente, ¡úsela!

Recomiendo usar accesorios en lugar de permitir el acceso a través de miembros públicos o clases de amigos.

No creo que usar la clase de amigos en realidad te brinde beneficios, y tiene el potencial de empeorar tu vida en el futuro. Si su código se mantendrá por mucho tiempo, existe una buena posibilidad de que pueda usarse de manera que no anticipe. Las funciones de acceso solo pueden usarse para las pruebas ahora, pero ¿quién sabe qué pasará en el futuro? El uso de accesorios en lugar de proporcionar acceso directo a las variables le brinda mucha más flexibilidad, y tiene un costo muy bajo.

El otro argumento es que usar accesorios en lugar de miembros públicos es un buen hábito. Desarrollar buenos hábitos es una habilidad importante como programador.

¿Qué tal hacer que el estado interno sea "protegido"? Y luego hace unittest usando clase derivada.

Creo que debe haber una distinción entre el futuro a prueba de la clase al proporcionar accesorios a sus usuarios si tiene sentido hacerlo y mejorar la capacidad de prueba. Tampoco soy un gran admirador de hacer amistad con las clases con el único propósito de las pruebas, ya que esto introduce un acoplamiento apretado en un lugar donde prefiero no tenerlo.

Si el único uso de los accesorios es proporcionar una forma para que los casos de prueba verifiquen el estado interno de la clase, normalmente no tiene sentido exponerlos públicamente. También puede atar los detalles de implementación que puede desear cambiar más adelante, pero luego descubrir que no puede porque alguien más está utilizando dichos accesorios.

Mi solución preferida para esto sería proporcionar protegido El accesorio funciona para comunicarse claramente a los usuarios de la clase que estos no son parte de la interfaz pública. Luego, sus pruebas crearían una clase derivada mínima del original que contiene trozos de llamada para las funciones de los padres, pero también hace que los accesorios sean públicos para que pueda usarlos en los casos de prueba.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top