¿Debería probar métodos privados o solo públicos?

He leído esta publicación sobre cómo probar métodos privados. Por lo general, no los pruebo, porque siempre pensé que era más rápido probar solo los métodos públicos que se llamarían desde fuera del objeto. ¿Probas métodos privados? ¿Debería probarlos siempre?

Yo no pruebo los métodos privados. Un método privado es un detalle de implementación que debe ocultarse a los usuarios de la clase. La prueba de métodos privados rompe la encapsulación.

Si encuentro que el método privado es enorme o complejo o lo suficientemente importante como para requerir sus propias pruebas, simplemente lo coloco en otra clase y lo hago público allí ( Objeto del Método ). Luego puedo probar fácilmente el método previamente privado pero ahora público que ahora vive en su propia clase.

¿Cuál es el propósito de las pruebas?

La mayoría de las respuestas hasta ahora dicen que los métodos privados son detalles de implementación que no (o al menos no deberían) importar siempre y cuando la interfaz pública esté bien probada y funcione. Eso es absolutamente correcto si su único propósito para las pruebas es garantizar que la interfaz pública funcione .

Personalmente, mi uso principal para las pruebas de código es garantizar que los futuros cambios de código no causen problemas y ayudar a mis esfuerzos de depuración si lo hacen. Considero que probar los métodos privados tan minuciosamente como la interfaz pública (¡si no más!) Fomenta ese propósito.

Considere lo siguiente: tiene el método público A que llama al método privado B. A y B utilizan el método C. C se modifica (quizás usted, quizás un proveedor), lo que hace que A comience a fallar sus pruebas. ¿No sería útil tener también pruebas para B, aunque sean privadas, para que sepas si el problema está en el uso por parte de A del uso de C de C, B o ambos?

La prueba de métodos privados también agrega valor en casos donde la cobertura de prueba de la interfaz pública es incompleta. Si bien esta es una situación que generalmente queremos evitar, la prueba de eficiencia de la unidad depende tanto de las pruebas que encuentren errores como de los costos asociados de desarrollo y mantenimiento de dichas pruebas. En algunos casos, los beneficios de la cobertura de prueba del 100% pueden considerarse insuficientes para justificar los costos de esas pruebas, lo que genera lagunas en la cobertura de prueba de la interfaz pública. En tales casos, una prueba bien dirigida de un método privado puede ser una adición muy efectiva a la base de código.

Tiendo a seguir los consejos de Dave Thomas y Andy Hunt en su libro Pragmatic Unit Testing :

En general, no desea romper ninguna encapsulación por el mero hecho de probar (o como solía decir su mamá, “¡no exponga sus partes privadas!”). La mayoría de las veces, usted debería poder evaluar una clase ejercitando sus métodos públicos. Si hay una funcionalidad significativa que se oculta detrás del acceso privado o protegido, podría ser una señal de advertencia de que hay otra clase que lucha por salir.

Pero a veces no puedo evitar probar métodos privados porque me da la sensación de que estoy construyendo un progtwig completamente sólido.

Me siento como obligado a probar las funciones privadas ya que estoy siguiendo cada vez más una de nuestras últimas recomendaciones de control de calidad en nuestro proyecto:

No más de 10 en complejidad ciclomática por función.

Ahora bien, el efecto secundario de hacer cumplir esta política es que muchas de mis funciones públicas muy grandes se dividen en muchas funciones privadas más centradas y mejor nombradas.
La función pública sigue ahí (por supuesto) pero se reduce esencialmente a llamar a todas esas ‘subfunciones’ privadas

Eso es realmente genial, porque la stack de llamadas ahora es mucho más fácil de leer (en lugar de un error dentro de una función grande, tengo un error en una sub-subfunción con el nombre de las funciones previas en la stack de llamadas para ayudarme a entender ‘cómo llegué allí’)

Sin embargo, ahora parece más fácil realizar una prueba unitaria directamente con esas funciones privadas , y dejar la prueba de la gran función pública en algún tipo de prueba de “integración” cuando se necesita abordar un escenario.

Solo mis 2 centavos.

Sí, sí realizo pruebas de funciones privadas, porque aunque se prueban con sus métodos públicos, es bueno en TDD (Test Driven Design) probar la parte más pequeña de la aplicación. Pero las funciones privadas no son accesibles cuando estás en tu clase de unidad de prueba. Esto es lo que hacemos para probar nuestros métodos privados.

¿Por qué tenemos métodos privados?

Las funciones privadas existen principalmente en nuestra clase porque queremos crear código legible en nuestros métodos públicos. No queremos que el usuario de esta clase llame a estos métodos directamente, sino a través de nuestros métodos públicos. Además, no queremos cambiar su comportamiento al extender la clase (en caso de protección), por lo tanto, es un privado.

Cuando codificamos, utilizamos Test-driven-design (TDD). Esto significa que a veces tropezamos con una funcionalidad privada y que queremos probar. Las funciones privadas no se pueden probar en phpUnit, porque no podemos acceder a ellas en la clase de prueba (son privadas).

Creemos que aquí hay 3 soluciones:

1. Puedes probar tus partes privadas a través de tus métodos públicos

Ventajas

  • Pruebas unitarias directas (no se necesitan ‘hacks’)

Desventajas

  • El progtwigdor necesita comprender el método público, mientras que solo quiere probar el método privado
  • No está probando la parte más pequeña comprobable de la aplicación

2. Si lo privado es tan importante, entonces tal vez sea un código para crear una nueva clase separada para él

Ventajas

  • Puede refactorizar esto a una nueva clase, porque si es tan importante, otras clases pueden necesitarlo también
  • La unidad comprobable ahora es un método público, por lo que se puede probar

Desventajas

  • No desea crear una clase si no es necesaria, y solo la usa la clase de donde proviene el método
  • Posible pérdida de rendimiento debido a gastos adicionales

3. Cambie el modificador de acceso a (final) protegido

Ventajas

  • Está probando la parte más pequeña comprobable de la aplicación. Al usar protección final, la función no será reemplazable (al igual que un privado)
  • Sin pérdida de rendimiento
  • Sin gastos adicionales

Desventajas

  • Está cambiando un acceso privado a protegido, lo que significa que es accesible para sus hijos
  • Todavía necesitas una clase simulada en tu clase de prueba para usarla

Ejemplo

 class Detective { public function investigate() {} private function sleepWithSuspect($suspect) {} } Altered version: class Detective { public function investigate() {} final protected function sleepWithSuspect($suspect) {} } In Test class: class Mock_Detective extends Detective { public test_sleepWithSuspect($suspect) { //this is now accessible, but still not overridable! $this->sleepWithSuspect($suspect); } } 

Entonces, nuestra unidad de prueba ahora puede llamar a test_sleepWithSuspect para probar nuestra función privada anterior.

Creo que es mejor simplemente probar la interfaz pública de un objeto. Desde el punto de vista del mundo exterior, solo importa el comportamiento de la interfaz pública y esto es a lo que deben dirigirse las pruebas de su unidad.

Una vez que haya escrito algunas pruebas de unidades sólidas para un objeto, no quiere tener que volver y cambiar esas pruebas solo porque la implementación detrás de la interfaz haya cambiado. En esta situación, ha arruinado la consistencia de las pruebas de su unidad.

Si el método privado está bien definido (es decir, tiene una función que es comprobable y no debe cambiar con el tiempo) entonces sí. Pruebo todo lo que es comprobable donde tiene sentido.

Por ejemplo, una biblioteca de cifrado puede ocultar el hecho de que realiza el cifrado en bloque con un método privado que encripta solo 8 bytes a la vez. Escribiría una prueba unitaria para eso: no está destinado a cambiar, aunque esté oculto, y si se rompe (debido a futuras mejoras de rendimiento, por ejemplo) entonces quiero saber que es la función privada la que se rompió, no solo que una de las funciones públicas se rompió.

Se acelera la depuración más tarde.

-Adán

Si su método privado no se prueba llamando a sus métodos públicos, ¿qué está haciendo? Estoy hablando de privado no protegido o amigo.

Si está desarrollando pruebas controladas (TDD), probará sus métodos privados.

No me gusta probar la funcionalidad privada por un par de razones. Son los siguientes (estos son los puntos principales para la gente de TLDR):

  1. Normalmente, cuando te sientes tentado a probar el método privado de una clase, es un olor de diseño.
  2. Puede probarlos a través de la interfaz pública (que es la forma en que desea probarlos, porque así es como el cliente los llamará / los usará). Puede obtener una falsa sensación de seguridad al ver la luz verde en todas las pruebas de aprobación de sus métodos privados. Es mucho mejor / más seguro probar casos extremos en sus funciones privadas a través de su interfaz pública.
  3. Se arriesga a una duplicación de prueba severa (pruebas que se ven / se sienten muy similares) al probar métodos privados. Esto tiene importantes consecuencias cuando cambian los requisitos, ya que muchas más pruebas de las necesarias se romperán. También puede colocarte en una posición en la que es difícil refactorizar debido a tu suite de pruebas … ¡lo cual es la máxima ironía, porque la suite de pruebas está ahí para ayudarte a rediseñar y refactorizar de forma segura!

Explicaré cada uno de estos con un ejemplo concreto. Resulta que 2) y 3) están un tanto intrincadamente conectados, por lo que su ejemplo es similar, aunque los considero como razones separadas por las que no debe probar métodos privados.

Hay una vez que considero que probar métodos privados es apropiado, pero lo analizaré con más detalle más adelante.

También repaso por qué TDD no es una excusa válida para probar métodos privados al final.

Refactorizando su salida de un mal diseño

Uno de los patrones (anti) más comunes que veo es lo que Michael Feathers llama una clase “Iceberg” (si no sabes quién es Michael Feathers, ve a comprar / lee su libro “Working Effectively with Legacy Code”. una persona que vale la pena saber si eres un ingeniero / desarrollador profesional de software). Hay otros (anti) patrones que hacen que surja este problema, pero este es de lejos el más común con el que he tropezado. Las clases de “Iceberg” tienen un método público, y el rest son privadas (razón por la cual es tentador probar los métodos privados). Se llama una clase “Iceberg” porque generalmente hay un método público solitario que surge, pero el rest de la funcionalidad está oculta bajo el agua en forma de métodos privados. Puede parecerse a esto:

Evaluador de reglas

Por ejemplo, es posible que desee probar GetNextToken() sucesivamente en una cadena y viendo que devuelve el resultado esperado. Una función como esta garantiza una prueba: ese comportamiento no es trivial, especialmente si sus reglas de tokenización son complejas. Imaginemos que no es tan complejo, y solo queremos encerrar tokens delimitados por el espacio. Entonces, usted escribe una prueba, tal vez se ve algo como esto (algún código psuedo agnóstico del idioma, con suerte la idea es clara):

 TEST_THAT(RuleEvaluator, canParseSpaceDelimtedTokens) { input_string = "1 2 test bar" re = RuleEvaluator(input_string); ASSERT re.GetNextToken() IS "1"; ASSERT re.GetNextToken() IS "2"; ASSERT re.GetNextToken() IS "test"; ASSERT re.GetNextToken() IS "bar"; ASSERT re.HasMoreTokens() IS FALSE; } 

Bueno, eso realmente se ve muy bien. Queremos asegurarnos de mantener este comportamiento mientras hacemos cambios. ¡Pero GetNextToken() es una función privada ! Así que no podemos probarlo así, porque ni siquiera comstackrá (suponiendo que estamos usando algún lenguaje que realmente haga cumplir lo público / privado, a diferencia de algunos lenguajes de scripting como Python). ¿Pero qué hay de cambiar la clase RuleEvaluator para seguir el Principio de Responsabilidad Individual (Principio de Responsabilidad Individual)? Por ejemplo, parece que tenemos un analizador, tokenizador y evaluador atascado en una clase. ¿No sería mejor simplemente separar esas responsabilidades? Además de eso, si creas una clase Tokenizer , entonces sus métodos públicos serían HasMoreTokens() y GetNextTokens() . La clase RuleEvaluator podría tener un objeto Tokenizer como miembro. Ahora, podemos mantener la misma prueba que la anterior, excepto que estamos probando la clase Tokenizer lugar de la clase RuleEvaluator .

Esto es lo que podría parecer en UML:

Evaluador de regla refactorizado

Tenga en cuenta que este nuevo diseño aumenta la modularidad, por lo que podría reutilizar estas clases en otras partes de su sistema (antes de que no pudiera, los métodos privados no son reutilizables por definición). Esta es la principal ventaja de romper el RuleEvaluator hacia abajo, junto con una mayor comprensibilidad / localidad.

La prueba se vería muy similar, excepto que en realidad se comstackría esta vez ya que el método GetNextToken() ahora es público en la clase Tokenizer :

 TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens) { input_string = "1 2 test bar" tokenizer = Tokenizer(input_string); ASSERT tokenizer.GetNextToken() IS "1"; ASSERT tokenizer.GetNextToken() IS "2"; ASSERT tokenizer.GetNextToken() IS "test"; ASSERT tokenizer.GetNextToken() IS "bar"; ASSERT tokenizer.HasMoreTokens() IS FALSE; } 

Prueba de componentes privados a través de una interfaz pública y evitando la duplicación de prueba

Incluso si no cree que pueda dividir su problema en menos componentes modulares (lo cual puede hacer el 95% del tiempo si solo intenta hacerlo), puede simplemente probar las funciones privadas a través de una interfaz pública. Muchas veces no vale la pena probar a los miembros privados porque se probarán a través de la interfaz pública. Muchas veces lo que veo son pruebas que se ven muy similares, pero pruebo dos funciones / métodos diferentes. Lo que termina sucediendo es que cuando los requisitos cambian (y siempre lo hacen), ahora tienes 2 pruebas rotas en lugar de 1. Y si realmente probabas todos tus métodos privados, podrías tener más de 10 pruebas rotas en lugar de 1. En resumen , probar funciones privadas (mediante el uso de FRIEND_TEST o hacerlas públicas o usar el reflection) que de otro modo podrían probarse a través de una interfaz pública puede causar la duplicación de las pruebas . Realmente no quieres esto, porque nada duele más que tu suite de pruebas que te frena. Se supone que disminuye el tiempo de desarrollo y disminuye los costos de mantenimiento. Si prueba métodos privados que de otro modo se prueban a través de una interfaz pública, el conjunto de pruebas puede hacer lo contrario y boost de forma activa los costos de mantenimiento y boost el tiempo de desarrollo. Cuando haces pública una función privada, o si usas algo como FRIEND_TEST y / o reflection, generalmente terminarás lamentándote a largo plazo.

Considere la siguiente implementación posible de la clase Tokenizer :

enter image description here

Digamos que SplitUpByDelimiter() es responsable de devolver una matriz de modo que cada elemento en la matriz sea un token. Además, digamos que GetNextToken() es simplemente un iterador sobre este vector. Entonces su prueba pública podría verse así:

 TEST_THAT(Tokenizer, canParseSpaceDelimtedTokens) { input_string = "1 2 test bar" tokenizer = Tokenizer(input_string); ASSERT tokenizer.GetNextToken() IS "1"; ASSERT tokenizer.GetNextToken() IS "2"; ASSERT tokenizer.GetNextToken() IS "test"; ASSERT tokenizer.GetNextToken() IS "bar"; ASSERT tokenizer.HasMoreTokens() IS false; } 

Hagamos de cuenta que tenemos lo que Michael Feather llama una herramienta de tientas . Esta es una herramienta que le permite tocar las partes privadas de otras personas. Un ejemplo es FRIEND_TEST de googletest o reflexión si el idioma lo admite.

 TEST_THAT(TokenizerTest, canGenerateSpaceDelimtedTokens) { input_string = "1 2 test bar" tokenizer = Tokenizer(input_string); result_array = tokenizer.SplitUpByDelimiter(" "); ASSERT result.size() IS 4; ASSERT result[0] IS "1"; ASSERT result[1] IS "2"; ASSERT result[2] IS "test"; ASSERT result[3] IS "bar"; } 

Bueno, ahora digamos que los requisitos cambian, y la tokenización se vuelve mucho más compleja. Usted decide que un delimitador de cadena simple no será suficiente, y necesita una clase Delimiter para manejar el trabajo. Naturalmente, esperará que se rompa una prueba, pero ese dolor aumenta cuando prueba funciones privadas.

¿Cuándo puede ser apropiado probar métodos privados?

No hay un “ajuste de talla única” en el software. A veces está bien (y en realidad es ideal) “romper las reglas”. Recomiendo firmemente no probar la funcionalidad privada cuando pueda. Hay dos situaciones principales cuando creo que está bien:

  1. He trabajado extensamente con sistemas heredados (razón por la cual soy tan fanático de Michael Feathers), y puedo decir con seguridad que a veces es simplemente lo más seguro probar la funcionalidad privada. Puede ser especialmente útil para obtener “pruebas de caracterización” en la línea de base.

  2. Tienes prisa y tienes que hacer lo más rápido posible aquí y ahora. A largo plazo, no querrás probar métodos privados. Pero diré que normalmente toma algún tiempo refactorizar para abordar problemas de diseño. Y a veces tienes que enviar en una semana. Está bien: haga lo rápido y sucio y pruebe los métodos privados usando una herramienta de tanteo, si esa es la forma más rápida y confiable de hacer el trabajo. Pero entienda que lo que hizo no era óptimo a la larga, y considere volver a él (o, si lo olvidó pero lo ve más tarde, corríjalo).

Probablemente haya otras situaciones en las que está bien. Si crees que está bien, y tienes una buena justificación, hazlo. Nadie te está deteniendo. Solo tenga en cuenta los costos potenciales.

La excusa TDD

Por otro lado, realmente no me gusta que las personas usen TDD como una excusa para probar métodos privados. Practico TDD, y no creo que TDD te obligue a hacer esto. Primero puede escribir su prueba (para su interfaz pública) y luego escribir el código para satisfacer esa interfaz. A veces escribo una prueba para una interfaz pública, y la satisfizo escribiendo uno o dos métodos privados más pequeños también (pero no pruebo los métodos privados directamente, pero sé que funcionan o mi prueba pública estaría fallando) ) Si necesito probar los casos límite de ese método privado, escribiré un montón de pruebas que llegarán a mi interfaz pública. Si no puede encontrar la manera de llegar a los casos extremos, esta es una fuerte señal de que necesita refactorizar en componentes pequeños, cada uno con sus propios métodos públicos. Es una señal de que las funciones privadas están haciendo demasiado y están fuera del scope de la clase .

Además, a veces encuentro que escribo una prueba que es demasiado difícil de masticar en este momento, y entonces pienso “eh volveré a esa prueba más tarde cuando tenga más de una API para trabajar” (I Lo comentaré y lo dejaré en el fondo de mi mente). Aquí es donde muchos de los desarrolladores que he conocido comenzarán a escribir pruebas para su funcionalidad privada, utilizando TDD como chivo expiatorio. Dicen “oh, bueno, necesito otra prueba, pero para escribir esa prueba, necesitaré estos métodos privados. Por lo tanto, dado que no puedo escribir ningún código de producción sin escribir una prueba, necesito escribir una prueba. para un método privado “. Pero lo que realmente necesitan hacer es refactorizar en componentes más pequeños y reutilizables en lugar de agregar / probar un montón de métodos privados a su clase actual.

Nota:

Respondí una pregunta similar sobre probar métodos privados usando GoogleTest hace un rato. En su mayoría, he modificado esa respuesta para ser más independiente del idioma aquí.

PS Aquí está la conferencia relevante sobre las clases de iceberg y las herramientas de tanteo de Michael Feathers: https://www.youtube.com/watch?v=4cVZvoFGJTU

No soy un experto en este campo, pero las pruebas unitarias deben probar el comportamiento, no la implementación. Los métodos privados son estrictamente parte de la implementación, por lo que en mi humilde opinión no deberían probarse.

Evaluamos los métodos privados por inferencia, lo que significa que buscamos una cobertura de prueba de clase total de al menos el 95%, pero solo nuestras pruebas requieren métodos públicos o internos. Para obtener la cobertura, debemos realizar múltiples llamadas al público / internos según los diferentes escenarios que puedan ocurrir. Esto hace que nuestras pruebas sean más exhaustivas con respecto al objective del código que están probando.

La respuesta de Trumpi a la publicación que vinculó es la mejor.

Pruebas unitarias que creo que son para probar métodos públicos. Sus métodos públicos usan sus métodos privados, por lo que indirectamente también se están probando.

He estado reflexionando sobre este tema durante un tiempo, especialmente con probar mi mano en TDD.

Me he encontrado con dos publicaciones que creo que abordan este problema a fondo en el caso de TDD.

  1. Prueba de métodos privados, TDD y refactorización controlada por prueba
  2. El desarrollo basado en pruebas no está probando

En resumen:

  • Cuando se utilizan técnicas de desarrollo impulsadas por pruebas (diseño), los métodos privados deben surgir solo durante el proceso de refactorización del código que ya está funcionando y probado.

  • Por la naturaleza misma del proceso, cualquier parte de la funcionalidad de implementación simple extraída de una función completamente probada será autoevaluada (es decir, cobertura de prueba indirecta).

Para mí, parece suficientemente claro que al principio parte de la encoding de la mayoría de los métodos serán funciones de nivel superior porque están encapsulando / describiendo el diseño.

Por lo tanto, estos métodos serán públicos y probarlos será bastante fácil.

Los métodos privados llegarán más tarde una vez que todo esté funcionando bien y estamos refaccionando en aras de la legibilidad y la limpieza .

Como se mencionó anteriormente, “si no prueba sus métodos privados, ¿cómo sabe que no se romperán?”

Este es un problema importante. Uno de los puntos importantes de las pruebas unitarias es saber dónde, cuándo y cómo algo se rompió lo antes posible. Por lo tanto, se reduce una cantidad significativa de desarrollo y esfuerzo de control de calidad. Si todo lo que se prueba es el público, entonces no se tiene una cobertura honesta y la delineación de las partes internas de la clase.

He encontrado que una de las mejores maneras de hacerlo es simplemente agregar la referencia de prueba al proyecto y colocar las pruebas en una clase paralela a los métodos privados. Coloque la lógica de comstackción adecuada para que las pruebas no se incluyan en el proyecto final.

Entonces usted tiene todos los beneficios de tener estos métodos probados y puede encontrar problemas en segundos en comparación con minutos u horas.

Entonces, en resumen, sí, prueba tus métodos privados.

Si no prueba sus métodos privados, ¿cómo sabe que no se romperán?

No deberias . Si sus métodos privados tienen suficiente complejidad que debe probarse, debe ponerlos en otra clase. Mantenga una alta cohesión , una clase debe tener un solo propósito. La interfaz pública de la clase debería ser suficiente.

Obviamente, depende del idioma. En el pasado con c ++, he declarado que la clase de prueba es una clase de amigos. Desafortunadamente, esto requiere que su código de producción sepa sobre la clase de prueba.

Entiendo el punto de vista donde los métodos privados se consideran detalles de implementaciones y luego no tienen que probarse. Y me quedaría con esta regla si tuviéramos que desarrollarnos fuera del objeto solamente. Pero nosotros, ¿somos algún tipo de desarrolladores restringidos que se desarrollan solo fuera de los objetos, llamando solo a sus métodos públicos? ¿O también estamos desarrollando ese objeto? Como no estamos obligados a progtwigr objetos externos, probablemente tendremos que llamar esos métodos privados a nuevos públicos que estamos desarrollando. ¿No sería genial saber que el método privado resiste contra todas las probabilidades?

I know some people could answer that if we are developing another public method into that object then this one should be tested and that’s it (the private method could carry on living without test). But this is also true for any public methods of an object: when developing a web app, all the public methods of an object are called from controllers methods and hence could be considered as implementation details for controllers.

So why are we unit testing objects? Because it is really difficult, not to say impossible to be sure that we are testing the controllers’ methods with the appropriate input which will trigger all the branches of the underlying code. In other words, the higher we are in the stack, the more difficult it is to test all the behaviour. And so is the same for private methods.

To me the frontier between private and public methods is a psychologic criteria when it comes to tests. Criteria which matters more to me are:

  • is the method called more than once from different places?
  • is the method sophisticated enough to require tests?

If we test to ensure the correctness of the logic, and a private method is carrying a logic, we should test it. ¿No es así? So why are we going to skip that?

Writing tests based on the visibility of methods is completely irrelevant idea.

If I find that the private method is huge or complex or important enough to require its own tests, I just put it in another class and make it public there (Method Object). Then I can easily test the previously private but now public method that now lives on its own class.

If the method is significant enough/complex enough , I’ll usually make it “protected” and test it. Some methods will be left private and tested implicitly as part of unit tests for the public/protected methods.

Absolutely YES. That is the point of Unit testing, you test Units. Private method is a Unit. Without testing private methods TDD (Test Driven Development) would be impossible,

I see many people are in the same line of thinking: test at the public level. but isn’t that what our QA team does? They test input and expected output. If as developers we only test the public methods then we are simply redoing QA’s job and not adding any value by “unit testing”.

The answer to “Should I test private methods?” is “…….sometimes”. Typically you should be testing against the interface of your classes.

  • One of the reasons is because you do not need double coverage for a feature.
  • Another reason is that if you change private methods, you will have to update each test for them, even if the interface of your object hasn’t changed at all.

Aquí hay un ejemplo:

 class Thing def some_string one + two end private def one 'aaaa' end def two 'bbbb' end end class RefactoredThing def some_string one + one_a + two + two_b end private def one 'aa' end def one_a 'aa' end def two 'bb' end def two_b 'bb' end end 

In RefactoredThing you now have 5 tests, 2 of which you had to update for refactoring, but your object’s functionality really hasn’t changed. So let’s say that things are more complex than that and you have some method that defines the order of the output such as:

 def some_string_positioner if some case elsif other case elsif other case elsif other case else one more case end end 

This shouldn’t be run by an outside user, but your encapsulating class may be to heavy to run that much logic through it over and over again. In this case maybe you would rather extract this into a seperate class, give that class an interface and test against it.

And finally, let’s say that your main object is super heavy, and the method is quite small and you really need to ensure that the output is correct. You are thinking, “I have to test this private method!”. Have you that maybe you can make your object lighter by passing in some of the heavy work as an initialization parameter? Then you can pass something lighter in and test against that.

No You shouldn’t test the Private Methods why? and moreover the popular mocking framework such as Mockito doesn’t provide support for testing private methods.