Pregunta

¿Cómo se prueba unitariamente una aplicación de interfaz de usuario MFC grande?

Tenemos algunas aplicaciones MFC grandes que han estado en desarrollo durante muchos años, utilizamos algunas herramientas de control de calidad automatizadas estándar para ejecutar scripts básicos para verificar los fundamentos, abrir archivos, etc.Estos son administrados por el grupo de control de calidad después de la compilación diaria.

Pero nos gustaría introducir procedimientos para que los desarrolladores individuales puedan crear y ejecutar pruebas en cuadros de diálogo, menús y otros elementos visuales de la aplicación antes de enviar el código a la compilación diaria.

He oído hablar de técnicas como botones de prueba ocultos en cuadros de diálogo que solo aparecen en compilaciones de depuración. ¿Existen kits de herramientas estándar para esto?

El entorno es C++/C/FORTRAN, MSVC 2005, Intel FORTRAN 9.1, Windows XP/Vista x86 y x64.

¿Fue útil?

Solución

Depende de cómo esté estructurada la aplicación.Si la lógica y el código GUI están separados (MVC), entonces probar la lógica es fácil.Echa un vistazo a Michael Feathers. "Cuadro de diálogo humilde" (PDF).

EDITAR:Si tú lo piensas:Debes refactorizar con mucho cuidado si la aplicación no está estructurada de esa manera.No existe otra técnica para probar la lógica.Los scripts que simulan clics son solo una muestra de ello.

En realidad es bastante fácil:

Suponga que su control/ventana/lo que sea cambia el contenido de un cuadro de lista cuando el usuario hace clic en un botón y desea asegurarse de que el cuadro de lista contenga lo correcto después del clic.

  1. Refactorice para que haya una lista separada con los elementos que se mostrarán en el cuadro de lista.Los elementos se almacenan en la lista y no se extraen de donde provengan sus datos.El código que hace que el cuadro de lista enumere cosas solo conoce la nueva lista.
  2. Luego crea un nuevo objeto controlador que contendrá el código lógico.El método que maneja el clic en el botón solo llama a mycontroller->ButtonWasClicked().No sabe sobre el cuadro de lista ni nada más.
  3. MyController::ButtonWasClicked() hace lo que se debe hacer para la lógica prevista, prepara la lista de elementos y le indica al control que se actualice.Para que eso funcione, necesita desacoplar el controlador y el control creando una interfaz (clase virtual pura) para el control.El controlador sólo conoce un objeto de ese tipo, no el control.

Eso es todo.El controlador contiene el código lógico y conoce el control sólo a través de la interfaz.Ahora puedes escribir pruebas unitarias regulares para MyController::ButtonWasClicked() burlándote del control.Si no tienes idea de lo que estoy hablando, lee el artículo de Michaels.Dos veces.Y nuevamente después de eso.
(Nota personal:hay que aprender a no tontear tanto)

Otros consejos

Como mencionaste MFC, supuse que tienes una aplicación que sería difícil de conseguir bajo un sistema de prueba automatizado.Observará los mejores beneficios de los marcos de pruebas unitarias cuando cree pruebas mientras escribe el código.Pero intentar agregar una nueva característica de manera basada en pruebas a una aplicación que no está diseñada para ser comprobable.Puede ser un trabajo duro y muy frustrante.

Ahora lo que voy a proponer es definitivamente trabajo duro..pero con un poco de disciplina y perseverancia verás los beneficios muy pronto.

  • Primero, necesitará algo de respaldo administrativo para que las nuevas correcciones tarden un poco más.Asegúrese de que todos entiendan por qué.
  • A continuación compre una copia del libro WELC.Léalo de cabo a rabo si tiene tiempo O, si tiene dificultades, escanee el índice para encontrar el síntoma que presenta su aplicación.Este libro contiene muchos buenos consejos y es justo lo que necesita cuando intenta que el código existente sea comprobable.alt text
  • Luego, para cada nueva solución/cambio, dedica algo de tiempo y comprende el área en la que vas a trabajar.Escriba algunas pruebas en una variante xUnit de su elección (disponible gratuitamente) para ejercitar el comportamiento actual.
  • Asegúrese de que todas las pruebas pasen.Escriba una nueva prueba que ejercite el comportamiento necesario o el error.
  • Escribe código para hacer pasar esta última prueba.
  • Refactorice sin piedad dentro del área bajo prueba para mejorar el diseño.
  • Repita para cada nuevo cambio que tenga que realizar en el sistema a partir de ahora.No hay excepciones a esta regla.
  • Ahora la tierra prometida:Pronto comenzarán a surgir islas cada vez mayores de código bien probado.Cada vez habrá más código incluido en el conjunto de pruebas automatizadas y los cambios serán cada vez más fáciles de realizar.Y eso se debe a que, lenta y seguramente, el diseño subyacente se vuelve más comprobable.

La salida fácil fue mi respuesta anterior.Esta es la salida difícil pero correcta.

Me doy cuenta de que esta es una pregunta anticuada, pero para aquellos de nosotros que todavía trabajamos con MFC, el marco de pruebas unitarias de Microsoft C++ en VS2012 funciona bien.

El Procedimiento General:

  1. Compile su proyecto MFC como una biblioteca estática
  2. Agregue un nuevo proyecto de prueba de unidad nativa a su solución.
  3. En el proyecto de prueba, agregue su proyecto MFC como referencia.
  4. En las Propiedades de configuración del proyecto de prueba, agregue los directorios de inclusión para sus archivos de encabezado.
  5. En el vinculador, las opciones de entrada agregan su MFC.lib;nafxcwd.lib;libcmtd.lib;
  6. En 'Ignorar bibliotecas predeterminadas específicas' agregue nafxcwd.lib;libcmtd.lib;
  7. En General, agregue la ubicación de su archivo lib exportado a MFC.

El https://stackoverflow.com/questions/1146338/error-lnk2005-new-and-delete-already-definited-in-libcmtd-libnew-obj tiene una buena descripción de por qué necesita nafxcwd.lib y libcmtd.lib.

La otra cosa importante que hay que comprobar en los proyectos heredados.En Propiedades de configuración general, asegúrese de que ambos proyectos utilicen el mismo 'Conjunto de caracteres'.Si su MFC utiliza un juego de caracteres de varios bytes, también necesitará la prueba de MS para hacerlo.

Aunque no es perfecto, lo mejor que he encontrado para esto es AutoIt. http://www.autoitscript.com/autoit3

"AutoIt v3 es un lenguaje de programación gratuito similar a BASIC diseñado para automatizar la GUI de Windows y la programación general.Utiliza una combinación de pulsaciones de teclas simuladas, movimiento del mouse y manipulación de ventanas/controles para automatizar tareas de una manera que no es posible o confiable con otros lenguajes (por ejemplo,VBScript y SendKeys).AutoIt también es muy pequeño, autónomo y se ejecutará en todas las versiones de Windows listas para usar, sin necesidad de molestos "tiempos de ejecución".

Esto funciona bien cuando tiene acceso al código fuente de la aplicación que se está ejecutando, porque puede usar el número de identificación del recurso de los controles que desea controlar.De esta manera, no tendrá que preocuparse por los clics simulados del mouse en píxeles concretos.Desafortunadamente, en una aplicación heredada, es posible que el ID del recurso no sea único, lo que puede causar problemas.Sin embargo.Es muy sencillo cambiar los ID para que sean únicos y reconstruirlos.

El otro problema es que encontrarás problemas de sincronización.No tengo una solución probada y verdadera para estos.Lo que he usado es prueba y error, pero claramente no es escalable.El problema es que el script de AutoIT debe esperar a que la aplicación de prueba responda a un comando antes de que el script emita el siguiente comando o verifique la respuesta correcta.A veces no es fácil encontrar un evento conveniente para esperar y observar.

Mi sensación es que, al desarrollar una nueva aplicación, insistiría en una forma coherente de indicar "LISTO".¡Esto sería útil para los usuarios humanos así como para los scripts de prueba!Esto puede ser un desafío para una aplicación heredada, pero quizás pueda introducirlo en puntos problemáticos y extenderlo lentamente a toda la aplicación a medida que continúa el mantenimiento.

Aunque no puede manejar el lado de la interfaz de usuario, realizo una prueba unitaria del código MFC utilizando la biblioteca Boost Test.Hay un artículo de Code Project sobre cómo comenzar:

Diseño de objetos robustos con Boost

Bueno, tenemos una de estas enormes aplicaciones MFC en el lugar de trabajo.Es un dolor gigantesco mantener o extender...Ahora es una enorme bola de barro, pero acumula dinero. De todos modos

  • Usamos robot racional para hacer pruebas de humo y similares.
  • Otro enfoque que ha tenido cierto éxito es crear un pequeño lenguaje específico para el producto y pruebas de guión que usan VBScript y algunos Control manejan la magia del espionaje.Convierta acciones comunes en comandos.p.ej.OpenDatabase sería un comando que a su vez inyectará los bloques de script necesarios para hacer clic en Menú principal > Archivo > "Abrir...".Luego crea hojas de Excel que son una serie de dichos comandos.Estos comandos también pueden tomar parámetros.Algo así como una prueba FIT...pero más trabajo.Una vez que tenga la mayoría de los comandos comunes identificados y los scripts listos.Se trata de seleccionar y ensamblar scripts (etiquetados por CommandID) para escribir nuevas pruebas.Un ejecutor de pruebas analiza estas hojas de Excel, combina todos los pequeños bloques del script en un script de prueba y lo ejecuta.

    1. Abrir base de datos "C: ests\MyDB"
    2. OpenDialog "Agregar modelo"
    3. AddModel "M0001", "MiModelo", 2.5, 100
    4. Presiona OK
    5. Guardar base de datos

HT

En realidad, hemos estado usando Rational Team Test y luego Robot, pero en discusiones recientes con Rational descubrimos que no tienen planes de admitir aplicaciones nativas x64 que se centren más en .NET, por lo que decidimos cambiar las herramientas de control de calidad automatizado.Esto es genial, pero los costos de la licencia no nos permiten habilitarlo para todos los desarrolladores.

Todas nuestras aplicaciones admiten una API COM para secuencias de comandos, que realizamos pruebas de regresión a través de VB, pero esto prueba la API y no la aplicación como tal.

Idealmente, me interesaría saber cómo las personas integran cppunit y marcos de pruebas unitarias similares en la aplicación a nivel de desarrollador.

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