¿Debo probar métodos privados o solo públicos?


He leído este post sobre cómo probar métodos privados. Normalmente no los pruebo, porque siempre pensé que es más rápido probar solo métodos públicos que serán llamados desde fuera del objeto. ¿Pruebas métodos privados? ¿Debería probarlos siempre?

Author: Community, 2008-09-19

26 answers

No hago pruebas unitarias de métodos privados. Un método privado es un detalle de implementación que debe ocultarse a los usuarios de la clase. Probar 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 pongo en otra clase y lo hago público allí (Objeto del método). Entonces puedo probar fácilmente el método antes privado pero ahora público que ahora vive en su propia clase.

 281
Author: jop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-30 15:26:17

¿Cuál es el propósito de la prueba?

La mayoría de las respuestas hasta ahora están diciendo que los métodos privados son detalles de implementación que no importan (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 probar es garantizar que la interfaz pública funciona.

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

Considere: Tiene el método público A que llama al método privado B. A y B ambos hacen uso del método C. C se cambia (tal vez por usted, tal vez por un proveedor), causando que A comience a fallar sus pruebas. ¿No sería útil tener pruebas para B también, a pesar de que es privado, para que sepa si el problema está en el uso de A de C, el uso de B de C, o ambos?

Probar métodos privados también agrega valor en los casos en que la cobertura de prueba de la interfaz pública es incompleta. Si bien esta es una situación que generalmente queremos evitar, las pruebas unitarias de eficiencia dependen tanto de las pruebas que encuentran errores como de los costos asociados de desarrollo y mantenimiento de esas pruebas. En algunos casos, los beneficios de la cobertura del 100% de las pruebas pueden considerarse insuficientes para justificar los costos de esas pruebas, lo que produce lagunas en la cobertura de las pruebas de la interfaz pública. En 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.

 257
Author: Dave Sherohman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-06 06:48:29

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

En general, no quieres romper ninguna encapsulación por el bien de pruebas (o como mamá solía decir, " ¡no expongas tus partes privadas!"). Mas del tiempo, usted debe ser capaz de probar una clase mediante el ejercicio de su métodos públicos. Si hay una funcionalidad significativa que está oculta detrás del acceso privado o protegido, que podría ser una señal de advertencia que hay hay otra clase luchando por salir.

Pero a veces no puedo dejar de probar métodos privados porque me da esa sensación de seguridad de que estoy construyendo un completamente programa robusto.

 133
Author: Rosellyne Thompson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-03-07 03:38:42

Me siento obligado a probar funciones privadas ya que estoy siguiendo más y más una de nuestras últimas recomendaciones de QA en nuestro proyecto:

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

Ahora el efecto secundario de la aplicación de esta política es que muchas de mis funciones públicas muy grandes se dividen en muchas funciones más enfocadas, mejor llamadas privadas.
La función pública sigue allí (por supuesto), pero se reduce esencialmente a se llama a todas esas 'sub-funciones'privadas

Eso es realmente genial, porque el paquete 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-sub-función con el nombre de las funciones anteriores en el paquete de llamadas para ayudarme a entender 'cómo llegué allí')

Sin embargo, ahora parece más fácil probar directamente esas funciones privadas , y dejar la prueba de la función pública grande a algún tipo de prueba de 'integración' donde un es necesario abordar el escenario.

Sólo mis 2 centavos.

 56
Author: VonC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:09:53

Sí pruebo funciones privadas, porque aunque son probadas por 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á en su 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 la usuario de esta clase para llamar a estos métodos directamente, pero a través de nuestros métodos públicos. Además, no queremos cambiar su comportamiento al extender la clase (en caso de protegido), por lo tanto es un privado.

Cuando codificamos, usamos test-driven-design (TDD). Esto significa que a veces nos topamos con una pieza de funcionalidad que es privada y queremos probar. Las funciones privadas no son probables en PHPUnit, porque no podemos acceder a ellas en la clase Test (son privadas).

Creemos que aquí son 3 soluciones:

1. Puede probar sus partes privadas a través de sus métodos públicos

Ventajas

  • Pruebas unitarias sencillas (no se necesitan 'hacks')

Desventajas

  • El programador necesita entender 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 es un codesmell para crear una nueva clase separada para él

Ventajas

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

Desventajas

  • No desea crear una clase si no es necesaria, y solo se usa por la clase de la que proviene el método
  • Potencial pérdida de rendimiento debido a la sobrecarga adicional

3. Cambiar el modificador de acceso a (final) protected

Ventajas

  • Está probando la parte más pequeña comprobable de la aplicación. Cuando usando final protected, la función no será anulable (solo como un privado)
  • Sin pérdida de rendimiento
  • Sin gastos adicionales

Desventajas

  • Está cambiando un acceso privado a protegido, lo que significa que es accesible por sus niños
  • Todavía necesita una clase Simulada en su 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);
  }
}

Así que nuestra unidad de prueba ahora puede llamar a test_sleepWithSuspect para probar nuestra antigua función privada.

 48
Author: eddy147,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-25 07:58:55

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

Una vez que tenga algunas pruebas unitarias sólidas escritas para un objeto, no querrá tener que volver atrás y cambiar esas pruebas solo porque la implementación detrás de la interfaz cambió. En esta situación, has arruinado la consistencia de tus pruebas unitarias.

 22
Author: 17 of 26,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 19:59:57

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

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

Acelera la depuración más tarde.

-Adam

 18
Author: Adam Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:11:39

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

 17
Author: chrissie1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:04:21

Si está desarrollando test driven (TDD), probará sus métodos privados.

 13
Author: Jader Dias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-11-16 17:08:44

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

  1. Típicamente cuando estás tentado a probar el método privado de una clase, es un olor a diseño.
  2. Puedes probarlos a través del público interfaz (que es la forma en que desea probarlos, porque así es como el cliente los llamará / usará). Usted puede obtener una falsa sensación de seguridad por ver la luz verde en todas las pruebas que pasan para su privado método. Es mucho mejor/más seguro probar casos de borde en sus funciones privadas a través de su interfaz pública.
  3. Corre el riesgo de duplicación severa de pruebas (pruebas que se ven / sienten muy similar) probando métodos privados. Esto tiene mayor consecuencias cuando los requisitos cambian, como muchas más pruebas que necesario se romperá. También puede ponerlo en una posición donde está difícil de refactorizar debido a su conjunto de pruebas...que es lo último ironía, porque la suite de pruebas está ahí para ayudarte de forma segura rediseñar ¡y refactor!

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

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

También repaso por qué el TDD no es una excusa válida para probar métodos privados en el muy fin.

Refactorizando tu salida de un mal diseño

Uno de los patrones (anti)más comunes que veo es lo que Michael Feathers llama una clase de "Iceberg" (si no sabes quién es Michael Feathers, compra/lee su libro "Working Effectively with Legacy Code". Es una persona que vale la pena conocer si usted es un ingeniero/desarrollador de software profesional). Hay otros patrones (anti)que hacen que este problema surja, pero esto es, con mucho, el la más común con la que me he topado. Las clases "Iceberg" tienen un método público, y el resto son privadas (por lo que es tentador probar los métodos privados). Se llama una clase "Iceberg" porque generalmente hay un método público solitario asomando, pero el resto de la funcionalidad está oculta bajo el agua en forma de métodos privados. Podría verse algo como esto:

Evaluador de Reglas

Por ejemplo, es posible que desee probar GetNextToken() invocándolo en una cadena sucesivamente y viendo que devuelve el resultado esperado. Una función como esta justifica una prueba: ese comportamiento no es trivial, especialmente si sus reglas de tokenización son complejas. Finjamos que no es tan complejo, y solo queremos encadenar fichas delimitadas por el espacio. Así que escribes una prueba, tal vez se vea algo como esto (algún código psuedo agnóstico del lenguaje, esperemos que la idea sea 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 en realidad se ve bastante bien. Nos gustaría asegurarnos de mantener este comportamiento como hacemos cambios. Pero GetNextToken() es una función privada ! Así que no podemos probarlo así, porque ni siquiera compilará (asumiendo que estamos usando algún lenguaje que realmente hace cumplir 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 Única (Principio de Responsabilidad Única)? Por ejemplo, parece que tenemos un analizador sintáctico, un tokenizador y un evaluador atascados 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 en lugar de la clase RuleEvaluator.

Esto es lo que podría parecer en UML:

Evaluador de Reglas 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, junto con una mayor comprensibilidad/localidad.

La prueba se vería extremadamente similar, excepto que en realidad se compilarí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;
}

Probar componentes privados a través de una interfaz pública y evitar la duplicación de pruebas

Incluso si no piensas puede dividir su problema en menos componentes modulares (que puede el 95% de las veces si solo intenta hacerlo), simplemente puede probar las funciones privadas a través de una interfaz pública. Muchas veces los miembros privados no valen la pena probar porque serán probados a través de la interfaz pública. Muchas veces lo que veo son pruebas que parecen muy similares, pero prueban dos funciones/métodos diferentes. Lo que termina sucediendo es que cuando los requisitos cambian (y siempre lo hacen), ahora tiene 2 pruebas rotas en lugar de 1. Y si realmente probaste todos tus métodos privados, podrías tener más como 10 pruebas rotas en lugar de 1. En resumen, probar funciones privadas (usando FRIEND_TEST o haciéndolas públicas o usando reflexión) que de otra manera podrían ser probadas a través de una interfaz pública puede causar duplicación de pruebas. Realmente no quieres esto, porque nada duele más que tu suite de pruebas que te ralentiza. Se supone que disminuye el tiempo de desarrollo y disminuye ¡costes de mantenimiento! Si prueba métodos privados que de otra manera se prueban a través de una interfaz pública, el conjunto de pruebas puede muy bien hacer lo contrario, y aumentar activamente los costos de mantenimiento y aumentar el tiempo de desarrollo. Cuando haces pública una función privada, o si usas algo como FRIEND_TEST y/o reflexión, generalmente terminarás lamentándolo a largo plazo.

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

introduzca la descripción de la imagen aquí

Vamos a digamos que SplitUpByDelimiter() es responsable de devolver un array tal que cada elemento en el array es un token. Además, digamos que GetNextToken() es simplemente un iterador sobre este vector. Así que 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;
}

Finjamos que tenemos lo que Michael Feather llama una herramienta de manoseo . Esta es una herramienta que te permite tocar las partes privadas de otras personas. Un ejemplo es FRIEND_TEST de googletest, o reflection si el lenguaje lo soporta.

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ás que una prueba se rompa, pero ese dolor aumenta cuando pruebas funciones privadas.

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

No hay una "talla única" en el software. A veces está bien (y en realidad es ideal) "romper las reglas". Yo defiendo firmemente no probar la funcionalidad privada cuando se puede. Hay dos situaciones principales cuando creo que está bien:

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

  2. Usted está en un apuro, y tiene que hacer lo más rápido posible para aquí y ahora. A la larga, no querrás probar métodos privados. Pero diré que por lo general toma algún tiempo refactorizar para abordar los problemas de diseño. Y a veces tienes que enviar en una semana. Eso está bien: haz lo rápido y sucio y prueba los métodos privados usando una herramienta de manoseo si eso es lo que crees que es la forma más rápida y confiable de hacer el trabajo. Pero comprenda que lo que hizo fue subóptimo a largo plazo, y por favor considere volver a él (o, si se olvidó pero lo ves más tarde, arreglarlo).

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

La excusa del TDD

Como un aparte, realmente no me gusta que la gente use TDD como una excusa para probar métodos privados. Practico TDD, y no creo que TDD te obligue a hacer esto. Usted puede escribir su prueba (para su interfaz pública) primero, y luego escribir código para satisfacer esa interfaz. A veces escribo una prueba para una interfaz pública, y la satisfaceré 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 casos extremos de ese método privado, escribiré un montón de pruebas que los golpearán a través de mi interfaz pública. Si no puede averiguar cómo golpear los casos extremos, esto es una fuerte señal de que necesita refactorizar en pequeños componentes, cada uno con sus propios métodos públicos. Es una señal de que las funciones privadas están haciendo demasiado, y fuera del alcance de la clase .

También, a veces encuentro que escribo una prueba que es demasiado grande para masticar en este momento, y así pienso "eh, volveré a esa prueba más tarde cuando tenga más de una API con la que trabajar" (lo comentaré y lo guardaré en el fondo de mi mente). Aquí es donde un montón de desarrolladores que he conocido entonces comience a escribir pruebas para su funcionalidad privada, usando TDD como chivo expiatorio. Dicen " oh, bueno, necesito alguna otra prueba, pero para escribir esa prueba, necesitaré estos métodos privados. Por lo tanto, como 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 actual clase.

Nota:

Respondí a 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 agnóstico del lenguaje aquí.

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

 12
Author: Matt Messersmith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-20 21:09:10

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 MIHO no debe ser probado.

 11
Author: maxbog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:00:05

Probamos métodos privados por inferencia, con lo que quiero decir que buscamos una cobertura total de prueba de clase de al menos 95%, pero solo hacemos que nuestras pruebas llamen a métodos públicos o internos. Para obtener la cobertura, necesitamos hacer múltiples llamadas al público / internos basados en los diferentes escenarios que pueden ocurrir. Esto hace que nuestras pruebas sean más intencionales en torno al propósito del código que están probando.

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

 11
Author: Tom Carr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:02:05

Las pruebas unitarias creo que son para probar métodos públicos. Sus métodos públicos utilizan sus métodos privados, por lo que indirectamente también están siendo probados.

 8
Author: scubabbl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 19:58:55

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

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

  1. Testing private methods, TDD and Test-Driven Refactoring
  2. El Desarrollo Basado en Pruebas No Está Probando

En Resumen:

  • Cuando se utilizan técnicas de desarrollo (diseño) impulsadas por pruebas, los métodos privados deben surgir solo durante el proceso de re-factoring de código ya en funcionamiento y probado.

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

Para mí parece bastante claro que en la parte inicial de la codificación 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 los métodos serán públicos y probarlos será bastante fácil.

Los métodos privados vendrán más tarde una vez que todo esté funcionando bien y estamos re factorizando por el bien de legibilidad y limpieza.

 7
Author: dkinzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-17 14:45:13

Como se mencionó anteriormente, "Si no pruebas tus métodos privados, ¿cómo sabes que no se romperán?"

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

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

Entonces tiene todos los beneficios de tener estos métodos probados y puede encontrar problemas en segundos versus minutos u horas.

Así que en resumen, sí, prueba unitaria tus métodos privados.

 5
Author: Adron,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-20 19:14:19

Si no pruebas tus métodos privados, ¿cómo sabes que no se romperán?

 4
Author: Billy Jo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 19:58:58

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

 4
Author: fernandezdavid7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-21 15:11:19

Obviamente depende del idioma. En el pasado con c++, he declarado la clase testing como una clase friend. Desafortunadamente, esto requiere que su código de producción conozca la clase de prueba.

 2
Author: dvorak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 20:01:14

Entiendo el punto de vista donde los métodos privados se consideran como detalles de implementaciones y luego no tienen que ser probados. Y me quedaría con esta regla si tuviéramos que desarrollar fuera del objeto solamente. Pero nosotros, ¿somos algún tipo de desarrolladores restringidos que están desarrollando solo fuera de los objetos, llamando solo a sus métodos públicos? ¿O estamos realmente desarrollando ese objeto? Como no estamos obligados a programar objetos externos, probablemente tendremos que llamar a esos métodos privados en nuevos públicos que estamos desarrollando. ¿No sería genial saber que el método privado resiste contra todo pronóstico?

Sé que algunas personas podrían responder que si estamos desarrollando otro método público en ese objeto, entonces este debería ser probado y eso es todo (el método privado podría continuar viviendo sin prueba). Pero esto también es cierto para cualquier método público de un objeto: al desarrollar una aplicación web, todos los métodos públicos de un objeto se llaman desde métodos controllers y, por lo tanto, podría considerarse como detalles de implementación para los controladores.

Entonces, ¿por qué estamos probando objetos unitarios? Porque es realmente difícil, por no decir imposible, estar seguro de que estamos probando los métodos de los controladores con la entrada adecuada que activará todas las ramas del código subyacente. En otras palabras, cuanto más alto estamos en la pila, más difícil es probar todo el comportamiento. Y lo mismo ocurre con los métodos privados.

Para mí la frontera entre privado y métodos públicos es un criterio psicológico cuando se trata de pruebas. Los criterios que más me importan son:

  • ¿se llama al método más de una vez desde diferentes lugares?
  • ¿es el método lo suficientemente sofisticado como para requerir pruebas?
 2
Author: Olivier Pichon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-06 23:22:19

Si probamos para asegurar la corrección de la lógica, y un método privado está llevando una lógica, debemos probarlo. ¿No lo es? Entonces, ¿por qué vamos a saltarnos eso?

Escribir pruebas basadas en la visibilidad de los métodos es una idea completamente irrelevante.

 2
Author: Supun Wijerathne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-11 07:00:32

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

 1
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-19 16:14:15

Si el método es lo suficientemente significativo/lo suficientemente complejo , generalmente lo haré "protegido" y lo probaré. Algunos métodos se dejarán privados y se probarán implícitamente como parte de las pruebas unitarias para los métodos públicos/protegidos.

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 08:39:57

Absolutamente SÍ. Ese es el punto de las pruebas unitarias, pruebas Unidades. El método privado es una Unidad. Sin probar métodos privados TDD (Test Driven Development) sería imposible,

 0
Author: Shpokas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-25 10:58:59

Veo que muchas personas están en la misma línea de pensamiento: probar a nivel público. ¿pero no es eso lo que hace nuestro equipo de control de calidad? Prueban la entrada y la salida esperada. Si como desarrolladores solo probamos los métodos públicos, simplemente estamos rehaciendo el trabajo de QA y no agregando ningún valor mediante "pruebas unitarias".

 0
Author: aemorales1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 15:01:02

La respuesta a "¿Debo probar métodos privados?" ser ".......a veces". Por lo general, deberías probar con la interfaz de tus clases.

  • Una de las razones es porque no necesitas doble cobertura para una función.
  • Otra razón es que si cambia los métodos privados, tendrá que actualizar cada prueba para ellos, incluso si la interfaz de su objeto no ha cambiado en absoluto.

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
{[3] {} En[2]} ahora tiene 5 pruebas, 2 de los cuales tuvo que actualizar para refactorizar, pero la funcionalidad de su objeto realmente no ha cambiado. Así que digamos que las cosas son más complejas que eso y tienes algún método que define el orden de la salida como:
def some_string_positioner
  if some case
  elsif other case
  elsif other case
  elsif other case
  else one more case
  end
end

Esto no debe ser ejecutado por un usuario externo, pero su clase de encapsulación puede ser demasiado pesada para ejecutar tanta lógica a través de ella una y otra vez. En este caso, tal vez prefiera extraer esto en una clase separada, darle a esa clase una interfaz y probar en contra.

Y finalmente, digamos que su objeto principal es súper pesado, y el método es bastante pequeño y realmente necesita asegurarse de que la salida sea correcta. Estás pensando, " ¡Tengo que probar este método privado!". ¿Tiene usted que tal vez usted puede hacer su objeto más ligero pasando en parte del trabajo pesado como un parámetro de inicialización? Entonces puedes pasar algo más ligero y probar contra eso.

 0
Author: unflores,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 15:52:14

No No deberías probar los Métodos Privados ¿por qué? y además el popular framework de burla como Mockito no proporciona soporte para probar métodos privados.

 0
Author: cammando,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:02:59