2009-09-02 18 views
7

Actualmente estoy reutilizando las pruebas JUnit 4 de otro proyecto contra mi código. Los obtengo directamente del repositorio del otro proyecto como parte de mi compilación Ant automatizada. Esto es genial, ya que asegura que mantengo mi código verde contra la última versión de las pruebas.Excluir métodos de prueba JUnit individuales sin modificar la clase de prueba?

Sin embargo, hay un subconjunto de pruebas que nunca espero pasar en mi código. Pero si empiezo a agregar anotaciones @Ignore a esas pruebas, tendré que mantener mi propia copia separada de la implementación de la prueba, que I realmente no quiero hacer.

¿Hay alguna manera de excluir las pruebas individuales sin modificar la fuente de prueba? Esto es lo que he visto hasta ahora:

  • Por lo que yo puedo ver, la tarea Ant JUnit sólo se le permite excluir clases de prueba completos, no a los métodos de ensayo individuales - por lo que no es bueno para mí, necesito granularidad del método.

  • Consideré armar un TestSuite que utiliza la reflexión para buscar y agregar dinámicamente todas las pruebas originales, luego agregar código para eliminar explícitamente las pruebas que no quiero ejecutar. Pero abandoné esa idea cuando noté que el TestSuite API no proporciona un método para eliminar las pruebas.

  • Puedo crear mis propias clases de prueba que extienden las clases de prueba originales, anulan las pruebas específicas que no quiero ejecutar y las anotan con @Ignore. Luego ejecuto JUnit en mis subclases. La desventaja aquí es que si se agregan nuevas clases de prueba al proyecto original, no las recogeré automáticamente. Tendré que supervisar las nuevas clases de prueba a medida que se agregan al proyecto original. Esta es mi mejor opción hasta ahora, pero no me parece ideal.

  • La única otra opción que se me ocurre es ejecutar las malas pruebas de todos modos e ignorar las fallas. Sin embargo, estas pruebas tardan un tiempo en ejecutarse (¡y fallan!) Por lo que preferiría no ejecutarlas en absoluto. Además, no veo una manera de decirle a la tarea Ant que ignore los fallos en los métodos de prueba específicos (una vez más, veo cómo se puede hacer para las clases de prueba individuales, pero no para los métodos).

Respuesta

4

Si no puede tocar la prueba original en absoluto, tendrá serias limitaciones. Su anulación suena como la mejor opción, pero con un par de cambios:

Cree las pruebas Ant excluyendo específicamente las super clases, para que se ejecuten clases adicionales que no conoce.

Puede usar la anotación @Rule (nueva en JUnit 4.7) para saber qué prueba se está ejecutando y cancelarla (devolviendo una implementación de Statement vacía) en lugar de anular métodos específicos, dándole más flexibilidad para saber si para evitar la prueba. El único problema con este método es que no puede detener la ejecución de los métodos @Before con este método, que puede ser lento. Si eso es un problema (y realmente no puedes tocar las pruebas) entonces @Ignore en el método reemplazado es lo único que se me ocurre.

Si, sin embargo, puede tocar esas pruebas, algunas opciones adicionales se abren:

usted podría funcionar con un corredor personales especificando la etiqueta @RunWith en la clase. Este corredor pasaría la ejecución al corredor estándar (JUnit4.clase) en ese proyecto, pero en su proyecto (a través de una propiedad del sistema o algún otro mecanismo) inspeccionaría el nombre de la prueba y no ejecutaría una prueba. Esto tiene la ventaja de ser el menos intrusivo, pero el más difícil de implementar (los corredores son bestias peludas, uno de los objetivos establecidos de @Rule era eliminar la mayor parte de la necesidad de hacerlos).

Otra es hacer una declaración de esa declaración en la prueba que verificaría alguna configuración que sería verdadera si esa prueba se ejecutara. Eso implicaría inyectar directamente en la prueba, lo que probablemente sea un factor decisivo en cualquier cosa remotamente etiquetada como un "proyecto separado".

0

Si las pruebas no deseados están en clases/paquetes específicos, se puede utilizar un conjunto de archivos excluir, en Ant para excluirlos durante la importación.

+0

No, desafortunadamente tengo que excluir métodos de prueba específicos. Es decir, quiero ejecutar algunas pruebas en una clase de prueba determinada, pero no en otras. – rewbs

2

OK, esta es una solución bastante pesada, pero no me arroje cosas si suena ridículo.

El núcleo de Junit4 es la clase org.junit.runner.Runner, y sus diversas subclases, lo más importante es org.junit.runners.Suite. Estos corredores determinan cuáles son las pruebas para una clase de prueba dada, utilizando elementos como @Test y @Ignore.

Es bastante fácil crear implementaciones personalizadas de un corredor, y normalmente las conectaría usando la anotación @RunWith en sus clases de prueba, pero obviamente esa no es una opción para usted.

Sin embargo, en teoría, podría escribir su propia tarea Ant, tal vez basada en la tarea Ant Junit estándar, que toma su corredor de prueba personalizado y lo usa directamente, pasando cada clase de prueba a la vez. La implementación de su corredor podría usar un archivo de configuración externo que especifique qué métodos de prueba ignorar.

Sería mucho trabajo, y tendrías que pasar tiempo buscando en la base de código Ant Junit prehistórica para descubrir cómo funciona. Sin embargo, la inversión en el tiempo puede valer la pena.

Es una lástima que la tarea Junit Ant no proporcione un mecanismo para especificar el Runner de prueba, que sería ideal.

+0

Diría que implementar un corredor es engañosamente simple. Me encontré copiando y pegando código de otras partes de JUnit para obtener una personalizada para que funcione correctamente, y fue muy frágil, casi como garantizar el lanzamiento de una nueva versión. – Yishai

+0

Todo es cierto. Nunca dije que fuera elegante :) – skaffman

1

Una posibilidad que se me ocurre para lograr lo que desea con las limitaciones establecidas es utilizar la modificación de bytecode. Puede mantener una lista de clases y métodos para ignorar en un archivo separado, y parchear el bytecode de las clases de prueba a medida que los carga para eliminar completamente estos métodos.

Si no me equivoco, JUnit utiliza la reflexión para encontrar los métodos de prueba para ejecutar. Una operación de cambio de nombre del método le permitiría eliminar estos métodos antes de que JUnit los encuentre. O el método puede modificarse para regresar inmediatamente, sin realizar ninguna operación.

Se puede usar una biblioteca como BCEL para modificar las clases cuando se cargan.

+1

JUnit 4 usa anotaciones en lugar de nombres de métodos para determinar las pruebas que se ejecutarán. – Yishai

+0

Sería válido modificar el método para devolverlo inmediatamente. Pero gracias, estaba pensando en JUnit3 –

+2

Presumiblemente, la modificación de bytecode también podría usarse para agregar anotaciones @Ignore a métodos en clases compiladas. – rewbs

3

No te ayuda ahora, pero TestNG es compatible con este tipo de habilidad.

1

Si desea ejecutar solo un subconjunto de las pruebas, parece que esa clase tiene más de una responsabilidad y debe rediseñarse. Alternativamente, la clase de prueba podría romperse para que el proyecto original tuviera todas las pruebas pero en una o más clases (supongo que algunas de las pruebas son realmente pruebas de integración y toque la base de datos o la red) y podría excluir la clase (es) que no querías.

Si no puede hacer nada de eso, su opción de anulación es probablemente la mejor. Tome el proceso de cuando necesite ignorar algunos métodos para extender esa clase y agregarla a su lista de exclusión de Ant. De esta forma, puede excluir lo que no puede aprobar y aún así obtener todas las pruebas nuevas (métodos que no anuló y nuevas clases de prueba) sin modificar su compilación.

0

dos opciones

  1. trabajar con el propietario de las pruebas tomadas para extraer sus seres en una clase separada que ambos puedan compartir.
  2. Crea tu propia clase de prueba que proxies la clase de prueba que deseas utilizar. Para cada método que desee incluir, tenga un método en su clase. Deberá construir una instancia de la clase de prueba a la que llama y también hacer antes y después de los métodos si están en el original.
  3. Cree un corredor Junit personalizado basado en blockjunitrunner y úselo para filtrar o en las pruebas que desee.
Cuestiones relacionadas