JavaRush /Blog Java /Random-ES /JUnit para JavaRush o un poco sobre pruebas en casa.
Sdu
Nivel 17

JUnit para JavaRush o un poco sobre pruebas en casa.

Publicado en el grupo Random-ES
¿Estás cansado de escribir datos de prueba en la consola docenas de veces para comprobar tu tarea? Bienvenido al gato, te diré qué puedes hacer con él. El objetivo final de este material será automatizar el lanzamiento de la tarea que se está resolviendo con varios parámetros y comprobar los resultados sin realizar cambios en su código fuente. Como probablemente ya entendiste por el título, nuestro asistente principal en este asunto bastante simple será JUnit . Si aún no has oído hablar de las pruebas unitarias y las pruebas unitarias , te sugiero que te tomes un pequeño descanso y te familiarices con estos conceptos, afortunadamente hay suficiente información en Internet. No, ¿no quieres? Bueno, está bien, creo que esto no será un gran problema para entender lo que está pasando. Después de todo, ¿sabes qué son una prueba y las pruebas en general? Haga esto cada vez que inicie su tarea, ingrese los datos iniciales y compare el resultado resultante con lo que esperaba ver.
¡Hola mundo JUnit!
¿Qué es JUnit? En la web oficial del proyecto podemos leer la siguiente descripción:
JUnit es un marco simple para escribir pruebas repetibles. Es una instancia de la arquitectura xUnit para marcos de pruebas unitarias.
Para nosotros, esto significa la capacidad de escribir clases especialmente diseñadas cuyos métodos interactuarán con nuestro programa, comparar el resultado resultante con el de referencia e informarnos si no coinciden. Para comprender el principio, consideremos un ejemplo sencillo. Supongamos que tenemos una clase auxiliar, uno de cuyos métodos toma dos variables de tipo int y devuelve su suma: JUnit para JavaRush o un poco sobre pruebas en casa.  - 1 esta es la funcionalidad que intentaremos probar. Afortunadamente, nuestra IDEA favorita ya tiene todo lo necesario para crear pruebas rápidamente, todo lo que necesitamos es colocar el cursor en la línea de declaración de clase, presionar "Alt + Enter" y seleccionar "Crear prueba" en el menú contextual: JUnit para JavaRush o un poco sobre pruebas en casa.  - 2 después de especificar dónde debe crear una prueba, IDEA sugiere elegir una biblioteca de prueba (en este material uso JUnit4; para que las clases de la biblioteca estén conectadas al proyecto, debe hacer clic en el botón "Reparar"), métodos a probar y adicionales opciones. JUnit para JavaRush o un poco sobre pruebas en casa.  - 3 El IDE creará una plantilla de clase de prueba: ClassName = TestClassName + "Test" MethodName = "test" + TestMethodName JUnit para JavaRush o un poco sobre pruebas en casa.  - 4 Solo necesitamos completar el cuerpo del método. Las llamadas “Aserciones” , métodos proporcionados por JUnit , ayudarán con esto . De manera simplificada, su trabajo se ve así: el resultado esperado y el resultado de llamar al método bajo prueba se pasan al método .assert*, para mayor comodidad, puede agregar un mensaje explicativo como primer parámetro. Si los parámetros no coinciden durante la prueba, se le informará al respecto. Puede iniciar una clase de prueba para su ejecución como una clase normal, prefiero usar la combinación de teclas Ctrl+Shift+F10 JUnit para JavaRush o un poco sobre pruebas en casa.  - 5
Especifiquemos la tarea
En teoría, todo es simple y hermoso, pero en el contexto del ejemplo propuesto, no es realmente necesario; podemos confiar en que la computadora suma dos números. Estamos más interesados ​​en cómo irán las cosas con problemas reales resueltos por estudiantes de JavaRush; por ejemplo, sugiero tomar el amado nivel05.lesson12.bonus03.
/* Problema con algoritmos Escriba un programa que: 1. ingrese el número N > 0 desde la consola 2. luego ingrese N números desde la consola 3. muestre el máximo de los N números ingresados. */
Necesitamos escribir tres pruebas, para números positivos, negativos y un conjunto mixto.
Cuanto más se adentra en el bosque...
Aquí es donde nos esperan algunas sorpresas: public class UtilApp { public static void main(String[] args) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); //напишите здесь ваш código int n; int maximum; /* Конечно же я не буду размещать решение задачи ;) Код приведенный тут переработан для наглядности, и не в коем случае не означает что он должен присутствовать в "правильном решении" */ System.out.println(maximum); } }
  • La lógica del programa se coloca en el método main().
  • Los datos de origen no se pasan al método, sino que se ingresan desde el teclado.
  • El método main() no devuelve el resultado, sino que lo envía a la consola.
Si el primer punto no es particularmente problemático (podemos llamar al método main() como de costumbre), los dos siguientes nos obligan a profundizar en el tema y esforzarnos. Encontré varias soluciones al problema:
  1. Mover la lógica para encontrar el máximo a un método separado.
    • Ventajas: enfoque correcto en términos de refactorización
    • Contras: El programa se llena de código, estructuras innecesarias, al menos se agrega una matriz o ArrayList (dependiendo del gusto y el color...). Sólo se prueba el mecanismo para encontrar el máximo; no se verifican la entrada y salida de datos.
  2. Escribir envoltorios para System.in/System.out.
    • Ventajas: No utilizamos bibliotecas de terceros.
    • Desventajas: El camino no es para principiantes. La complejidad relativa de la implementación de la prueba; la cantidad de código en la prueba puede ser mayor que en la tarea que se está probando.
  3. Uso de bibliotecas adicionales para pruebas.
    • Ventajas: código limpio en las pruebas, relativa facilidad para escribir una prueba. El código fuente de la clase bajo prueba no cambia.
    • Contras: Necesidad de conectar bibliotecas de terceros al proyecto.
Para ser honesto, la tercera opción me gustó más, así que intentemos implementarla.
Reglas del sistema
Una breve búsqueda me llevó a la página http://stefanbirkner.github.io/system-rules/ e inmediatamente quedó claro que esto era lo que necesitaba.
Una colección de reglas JUnit para probar código que usa java.lang.System.
Entonces, descarguemos la biblioteca . Descargue la biblioteca Commons IO necesaria para que funcionen las reglas del sistema . Conectamos ambas bibliotecas a nuestro proyecto (Archivo -> Estructura del proyecto -> Bibliotecas -> + -> Java) y comenzamos a esculpir: Después del lanzamiento, nuestra tarea le pide que ingrese N+1 números desde la consola, donde el primer número le indica ¿Cuántos números lo seguirán? En System Rules se utiliza para estos fines la clase TextFromStandardInputStream, inicialmente debemos agregar un campo de este tipo a nuestra clase de prueba y marcarlo con la anotación @Rule: @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); Luego, directamente en el método de prueba indicamos los datos necesarios: systemInMock.provideText("4\n2\n6\n1\n3\n"); Como puede ver, los números se transmiten en forma de texto y están separados por un guión "\n". En base a esto, resulta que N será igual a 4, y buscaremos el máximo a partir de los números {2, 6, 1, 3}. A continuación, necesitamos crear una instancia de la clase bajo prueba y llamar al método main(). Nuestro programa lee los datos de systemInMock, los procesa e imprime el resultado, y todo lo que tenemos que hacer es leerlo y compararlo con el estándar. Para ello, las reglas del sistema nos proporcionan la clase StandardOutputStreamLog. Agregamos un campo del tipo especificado: @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); Puede leer los datos impresos usando el método .getLog(), aunque debe tener en cuenta la presencia de caracteres de nueva línea, las opciones finales pueden ser así: assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); // o assertEquals("{2, 6, 1, 3}, max = 6", "6\r\n", log.getLog()); Entre pruebas, para Evite la superposición de datos, debe borrar el registro log.clear(); El texto completo de mi clase de prueba: import org.junit.Rule; import org.junit.Test; import org.junit.contrib.java.lang.system.StandardOutputStreamLog; import org.junit.contrib.java.lang.system.TextFromStandardInputStream; import static org.junit.Assert.*; import static org.junit.contrib.java.lang.system.TextFromStandardInputStream.emptyStandardInputStream; public class UtilAppTest { @Rule public final TextFromStandardInputStream systemInMock = emptyStandardInputStream(); @Rule public final StandardOutputStreamLog log = new StandardOutputStreamLog(); @Test public void testAddition() throws Exception { systemInMock.provideText("4\n2\n6\n1\n3\n"); UtilApp utilApp = new UtilApp(); utilApp.main(new String[]{}); assertEquals("{2, 6, 1, 3}, max = 6", "6", log.getLog().trim()); systemInMock.provideText("5\n-100\n-6\n-15\n-183\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{-100, -6, -15, -183, -1}, max = -1", "-1", log.getLog().trim()); systemInMock.provideText("3\n2\n0\n-1\n"); log.clear(); utilApp.main(new String[]{}); assertEquals("{2, 0, -1}, max = 2", "2", log.getLog().trim()); } } Lanzamos y disfrutamos. -=!!! ¡¡¡IMPORTANTE!!!=- Este material se proporciona ÚNICAMENTE con fines informativos; no garantizo la prueba exitosa de la tarea en el servidor si hay una clase extraña en el paquete con la tarea. Antes de enviar una tarea para verificación al servidor, elimine todo lo superfluo: archivos innecesarios, clases innecesarias, código comentado. La finalización exitosa de las pruebas que ha creado no garantiza la finalización exitosa de las pruebas en el servidor. Deliberadamente no profundicé en el material teórico: teoría de las pruebas unitarias, anotaciones JUnit, afirmaciones, etc., todo el material está en los enlaces proporcionados en el texto. Quizás tenga sus propias formas de probar tareas; estaré encantado de comentarlas con usted en los comentarios.
Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION