Pregunta

Como desarrollador novato que está cogiendo el ritmo de mi primer proyecto profesional, estoy intentando desarrollar buenos hábitos lo antes posible.Sin embargo, descubrí que a menudo me olvido de probar, posponerlo o hacer un montón de pruebas al final de una compilación en lugar de una a la vez.

Mi pregunta es qué ritmo le gusta seguir cuando trabaja en proyectos grandes y dónde encajan las pruebas.

¿Fue útil?

Solución

Bueno, si quieres seguir a los chicos de TDD, antes de comenzar a codificar ;)

Estoy muy en la misma situación que tú.Quiero dedicarme más a las pruebas, pero actualmente estoy en una posición en la que estamos trabajando para "sacar el código" en lugar de "sacar el código correctamente", lo que me asusta muchísimo.Así que poco a poco estoy intentando integrar los procesos de prueba en mi ciclo de desarrollo.

Actualmente, Pruebo mientras codifico, tratando de romper el código mientras lo escribo.Me resulta difícil adoptar la mentalidad TDD.Está tomando tiempo, pero así es como lo haría. desear trabajar..

EDITAR:

Pensé que probablemente debería ampliar esto, este es mi "proceso de trabajo" básico...

  1. Planifique lo que quiero del código, posible diseño de objetos, lo que sea.
  2. Cree mi primera clase, agregue un comentario enorme a la parte superior que describe cuál es mi "visión" para la clase.
  3. Describe los escenarios de prueba básicos.Estos básicamente se convertirán en las pruebas unitarias.
  4. Crea mi primer método..También escribiendo un breve comentario explicando cómo es esperado trabajar.
  5. Escriba una prueba automatizada para ver si hace lo que espero.
  6. Repita los pasos 4 a 6 para cada método (tenga en cuenta que las pruebas automatizadas están en una lista enorme que se ejecuta en F5).
  7. Luego creo algunas pruebas completas para emular la clase en el entorno de trabajo, obviamente solucionando cualquier problema.
  8. Si sale a la luz algún error nuevo después de esto, vuelvo y escribo la nueva prueba, me aseguro de que falle (esto también sirve como prueba de concepto para el error) y luego lo soluciono.

Espero que eso ayude..Abierto a comentarios sobre cómo mejorar esto, como dije, es una preocupación mía.

Otros consejos

Antes de registrar el código.

Primero y con frecuencia.Si estoy creando alguna funcionalidad nueva para el sistema, buscaré definir inicialmente las interfaces y luego escribir pruebas unitarias para esas interfaces.Para determinar qué pruebas escribir, considere la API de la interfaz y la funcionalidad que proporciona, tome papel y lápiz y piense por un momento en posibles condiciones de error o formas de demostrar que está haciendo el trabajo correcto.Si esto es demasiado difícil, es probable que su API no sea lo suficientemente buena.Con respecto a las pruebas, vea si puede evitar escribir pruebas de "integración" que prueben más de un objeto específico y mantenerlas como pruebas "unitarias".

Luego cree una implementación predeterminada de su interfaz (que no haga nada, devuelva valores basura pero no arroje excepciones), conéctela a las pruebas para asegurarse de que las pruebas fallen (¡esto prueba que sus pruebas funcionan!:) ).Luego escriba la funcionalidad y vuelva a ejecutar las pruebas.Este mecanismo no es perfecto, pero cubrirá muchos errores de codificación simples y le brindará la oportunidad de ejecutar su nueva función sin tener que conectarla a toda la aplicación.

Después de esto, deberá probarlo en la aplicación principal con la combinación de funciones existentes.Aquí es donde las pruebas son más difíciles y, si es posible, se deben subcontratar parcialmente a un buen evaluador de control de calidad, ya que tendrán la habilidad de romper cosas.Aunque ayuda si tú también tienes estas habilidades.Realizar las pruebas correctamente es una habilidad que debes adquirir para ser honesto.Mi propia experiencia proviene de mis propias implementaciones ingenuas y los errores posteriores que informaron los usuarios cuando lo usaron con ira.

Al principio, cuando esto me sucedió, me pareció irritante que el usuario intentara intencionalmente dañar mi software y quería marcar todos los "errores" como "problemas de entrenamiento".Sin embargo, después de reflexionar sobre ello, me di cuenta de que es nuestro papel (como desarrolladores) hacer que la aplicación sea lo más simple y confiable posible para que la usen incluso los idiotas.Nuestro papel es empoderar a los idiotas y es por eso que nos pagan el dólar.Manejo idiota.

Para realizar una prueba de este tipo de forma eficaz, debes adoptar la mentalidad de intentar romperlo todo.Asuma el papel de un usuario que presiona los botones y generalmente intenta destruir su aplicación de maneras extrañas y maravillosas.Suponga que si no encuentra fallas, se descubrirán en la producción, lo que causará una grave pérdida de prestigio a su empresa.Asuma toda la responsabilidad por todos estos problemas y maldígase cuando se descubra en producción un error del que sea responsable (o incluso parcialmente responsable).

Si hace la mayor parte de lo anterior, entonces debería comenzar a producir un código mucho más robusto; sin embargo, es una forma de arte y requiere mucha experiencia para ser bueno.

Una buena clave para recordar es

"Pruebe temprano, pruebe con frecuencia y vuelva a realizar la prueba cuando crea que ha terminado"

¿Cuándo realizar la prueba?¡Cuando es importante que el código funcione correctamente!

Cuando pirateo algo para mí, lo pruebo al final.Mala práctica, pero normalmente son cosas pequeñas que usaré un par de veces y listo.

En un proyecto más grande, escribo pruebas antes de escribir una clase y ejecuto las pruebas después de cada cambio en esa clase.

Hago pruebas constantemente.Después de terminar incluso un bucle dentro de una función, ejecuto el programa y llego a un punto de interrupción en la parte superior del bucle, luego lo ejecuto.Todo esto es solo para asegurarme de que el proceso esté haciendo exactamente lo que quiero.

Luego, una vez finalizada una función, la pruebas en su totalidad.Probablemente desee establecer un punto de interrupción justo antes de llamar a la función y verificar su depurador para asegurarse de que funcione perfectamente.

Supongo que diría:"Pruebe con frecuencia".

Recientemente agregué pruebas unitarias a mi flujo de trabajo habitual, pero escribo pruebas unitarias:

  • para expresar los requisitos para cada nuevo módulo de código (justo después de escribir la interfaz pero antes de escribir la implementación)
  • cada vez pienso "que fuera mejor...para cuando termine "
  • cuando algo se rompe, para cuantificar el error y demostrar que lo he solucionado
  • cuando escribo código que asigna o desasigna memoria explícitamente, detesto buscar pérdidas de memoria...

Ejecuto las pruebas en la mayoría de las compilaciones y siempre antes de ejecutar el código.

Comience con las pruebas unitarias.Específicamente, consulte TDD, desarrollo basado en pruebas.El concepto detrás de TDD es que primero se escriben las pruebas unitarias y luego se escribe el código.Si la prueba falla, regresa y vuelve a trabajar en su código.Si pasa, pasas al siguiente.

Adopto un enfoque híbrido para TDD.No me gusta escribir pruebas contra nada, por lo que normalmente escribo parte del código primero y luego pongo las pruebas unitarias.Es un proceso iterativo, uno con el que nunca terminas.Cambias el código, ejecutas tus pruebas.Si hay alguna falla, corríjala y repita.

El otro tipo de pruebas son las pruebas de integración, que se realizan más adelante en el proceso y, por lo general, las puede realizar un equipo de pruebas de control de calidad.En cualquier caso, las pruebas de integración abordan la necesidad de probar las piezas en su conjunto.Lo que le preocupa probar es el producto funcional.Este es más difícil de manejar porque generalmente implica tener herramientas de prueba automatizadas (como Robot, por ejemplo).

Además, eche un vistazo a un producto como CruiseControl.NET para realizar compilaciones continuas.CC.NET es bueno porque ejecutará sus pruebas unitarias con cada compilación y le notificará inmediatamente sobre cualquier falla.

No hacemos TDD aquí (aunque algunos lo han recomendado), pero nuestra regla es que se supone que debes verificar tus pruebas unitarias con tus cambios.No siempre sucede, pero es fácil regresar y observar un conjunto de cambios específico y ver si se escribieron pruebas o no.

Encuentro que si espero hasta el final de escribir alguna característica nueva para probar, olvido muchos de los casos extremos que pensé que podrían romper la característica.Esto está bien si haces cosas para aprender por ti mismo, pero en un entorno profesional, creo que mi flujo es la forma clásica de:Rojo, Verde, Refactor.

Rojo:Escribe tu prueba para que falle.De esa manera sabrá que la prueba se valida con la variable correcta.

Verde:Haz que tu nuevo test pase de la forma más sencilla posible.Si eso significa codificarlo, está bien.Esto es genial para aquellos que sólo quieren que algo funcione de inmediato.

Refactorizar:Ahora que su prueba pasó, puede regresar y cambiar su código con confianza.¿Tu nuevo cambio superó tu prueba?Genial, tu cambio tuvo una implicación que no te diste cuenta, ahora tu prueba te lo dice.

¡Este ritmo me ha hecho acelerar mi desarrollo con el tiempo porque básicamente tengo un compilador de historial para todas las cosas que pensé que debían verificarse para que una función funcionara!Esto, a su vez, conduce a muchos otros beneficios, a los que no llegaré aquí...

¡Muchas respuestas geniales aquí!

Intento realizar pruebas en el nivel más bajo que tenga sentido:

  • Si un solo cálculo o condicional es difícil o complejo, agregue código de prueba mientras lo escribe y asegúrese de que cada parte funcione.Comente el código de prueba cuando haya terminado, pero déjelo ahí para documentar cómo probó el algoritmo.

  • Pruebe cada función.

    • Ejercite cada rama al menos una vez.
    • Ejercita el condiciones de borde - valores de entrada en los que el código cambia su comportamiento - para detectar errores "por uno".
    • Pruebe varias combinaciones de entradas válidas e inválidas.
    • Busque situaciones que puedan romper el código y pruébelas.
  • Pruebe cada módulo con la misma estrategia que la anterior.

  • Pruebe el cuerpo del código en su conjunto para asegurarse de que los componentes interactúen correctamente.Si ha sido diligente con las pruebas de nivel inferior, esto es esencialmente una "prueba de confianza" para garantizar que nada se rompa durante el ensamblaje.

Dado que la mayor parte de mi código es para dispositivos integrados, presto especial atención a la solidez, la interacción entre varios subprocesos, tareas y componentes, y el uso inesperado de recursos:memoria, CPU, espacio del sistema de archivos, etc..

En general, cuanto antes encuentre un error, más fácil será aislarlo, identificarlo y solucionarlo, y más tiempo podrá dedicar a crear, en lugar de perseguir su cola.*

**¡Lo sé, -1 para la referencia gratuita al puntero del búfer!*

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top