16

[Por supuesto, la cuestión no se limita a una aplicación "amigo" específica, no dude embargo señalar implementaciones específicas si es relevante]Uso de las declaraciones "friend" para pruebas unitarias. ¿Mala idea?

Lectura a través de las preguntas sin respuesta, yo nos topamos con el atributo InternalsVisibleTo:

Especifica que tipos que son ordinariamente visible sólo dentro del conjunto actual son visibles para otro conjunto.

El C# Programming Guide en MSDN tiene una sección Friend Assemblies que describe cómo utilizar el atributo para permitir el uso de internal métodos y tipos a otro conjunto.

Me pregunto si sería una buena idea utilizar esto para crear una interfaz "oculta" para instrumentar una biblioteca para el uso del conjunto de prueba de la unidad. Parece aumentar el acoplamiento de forma masiva en ambas direcciones (código de prueba en el conjunto de producción, conocimiento interno íntimo sobre el ensamblaje de producción en el código de prueba), pero por otro lado podría ayudar a crear pruebas detalladas sin saturar la interfaz pública.

¿Cuál es su experiencia con el uso de declaraciones de amigos durante las pruebas? ¿Fue su Silver Bullet o comenzó la Marcha de la Muerte?

Respuesta

13

He hecho un uso extensivo de esta técnica, significa que mis pruebas unitarias pueden probar aspectos de la biblioteca de códigos que no son visibles para los consumidores normales.

Si bien el uso de [InternalsVisibleTo] aumenta el acoplamiento, creo que el aumento (menor) bien vale las ganancias.

Mis pruebas unitarias ya están estrechamente relacionadas con el código bajo prueba -aunque trato de escribir pruebas que aseguren resultados específicos, no implementaciones específicas, accediendo a cosas que no son visibles para los consumidores habituales, de alguna manera obligo la implementación.

Yendo la otra manera, el acoplamiento es mínimo - en tener el atributo [InternalsVisibleTo] en el conjunto de código, y en el marcado de algunas cosas como interna en lugar de privado (o interna protegida en lugar de protegido) .

(Tenga en cuenta que estoy aquí haciendo caso omiso de cualquier cambio de diseño que son provocados por el uso de la Unidad de Pruebas, que es un conjunto de otros análisis.)

El atributo [InternalsVisibleTo] requiere una fuerte nombrar sus asambleas. Si aún no lo hace, puede encontrar esto un poco oneroso ya que un ensamble con un nombre fuerte solo puede depender de otros ensamblajes fuertemente nombrados, lo que puede terminar con la necesidad de modificar varios ensamblajes.

Obtener el atributo correcto puede ser un poco complicado, ya que debe incluir la clave pública de su ensamblaje de prueba. IDesign tiene un útil Friend Assembly tool que crea el atributo en su portapapeles, listo para pegar. Recomendado.

+0

¡Gracias por la sugerencia de una buena denominación! No estaba (todavía) al tanto de esto, pero como creo que todas mis asambleas deben ser llamadas con fuerza para su lanzamiento, no veo esto como un problema real. –

12

Es el único uso que he aplicado personalmente al InternalsVisibleTo, y ha sido muy, muy útil.

No veo las pruebas unitarias como pruebas de caja negra, ya están unidas a la implementación en cierta medida. Ser capaz de probar métodos y tipos internos permite un enfoque mucho más ajustado (unidades más pequeñas).

3

Creo que usar InternalsVisibleToAttribute para permitir la prueba unitaria es perfectamente razonable. Mi "unidad" en "pruebas unitarias" es una clase, y eso incluye clases internal, por lo que quiero probarlas. I don't want to unit test private methods, sin embargo.

No creo que sea una buena idea crear una interfaz especial y privada solo para pruebas. Uno de los valores de las pruebas unitarias es que le da la oportunidad de pensar en la interfaz de su clase desde el punto de vista de un consumidor de esa clase; proporcionar una puerta trasera le quita ese beneficio.

Mi preferencia, sin embargo, es poner mis pruebas unitarias en el mismo ensamblaje que mi código de producción. Por lo general, no afecta a mi cliente, pero me simplifica las cosas, así que lo hago. Cuando lo hago, hace que la pregunta InternalsVisibleTo desaparezca.

3

De hecho, Unit Testing es el único uso de que he podido utilizar para el InternalsVisibleToAttribute para. Con esto, puede implementar una gran parte de sus métodos "privados" como internos para exponerlos al marco de pruebas de la unidad para realizar pruebas más invasivas de invariantes internos de clase.

He tenido un gran éxito con esta técnica. Si nada más lo ayuda a abordar ese mítico objetivo de cobertura de código al 100% al permitirle invocar métodos privados en situaciones que de otro modo serían inaccesibles.

2

Creo que aparece otro caso de uso legítimo cuando ha utilizado ensamblajes separados al unir el código de C++ heredado con el código de C# más nuevo.

Hemos tomado los ensamblajes de C++, los convertimos a C++/CLI, y luego implementamos el código más nuevo en C#. Cuando hagamos esto, aún usaríamos "interno" para las clases/métodos en C# que no son realmente públicos, y luego los pondremos a disposición del código heredado como ensamblajes amigos.

Cuestiones relacionadas