Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
IntelliTest genera entradas para pruebas unitarias parametrizadas mediante el análisis de las condiciones de rama en el programa. Las entradas de prueba se eligen en función de si pueden desencadenar nuevos comportamientos de bifurcación del programa. El análisis es un proceso incremental. Refina un predicado q: I -> {true, false} sobre los parámetros de entrada de prueba formales I.
q representa el conjunto de comportamientos que IntelliTest ya ha observado. Inicialmente, , q := falseya que aún no se ha observado nada.
Los pasos del bucle son:
IntelliTest determina las entradas
ide forma queq(i)=falsese use un solucionador de restricciones. Por construcción, la entradaitomará una ruta de acceso de ejecución no vista previamente. Inicialmente, esto significa queipuede ser cualquier entrada, porque aún no se ha detectado ninguna ruta de acceso de ejecución.IntelliTest ejecuta la prueba con la entrada
ielegida y supervisa la ejecución de la prueba y el programa sometido a prueba.Durante la ejecución, el programa toma una ruta de acceso determinada que viene determinada por todas las ramas condicionales del programa. El conjunto de todas las condiciones que determinan la ejecución se denomina condición de ruta de acceso, escrita como predicado
p: I -> {true, false}sobre los parámetros de entrada formales. IntelliTest calcula una representación de este predicado.IntelliTest establece
q := (q or p). En otras palabras, registra el hecho de que ha visto la ruta de acceso representada porp.Vaya al paso 1.
El solucionador de restricciones de IntelliTest puede tratar los valores de todos los tipos que pueden aparecer en programas .NET:
IntelliTest filtra las entradas que infringen las suposiciones indicadas.
Además de las entradas inmediatas (argumentos para pruebas unitarias parametrizadas), una prueba puede obtener más valores de entrada de la clase estática PexChoose. Las opciones también determinan el comportamiento de los simulacros con parámetros.
Solucionador de restricciones
IntelliTest usa un solucionador de restricciones para determinar los valores de entrada pertinentes de una prueba y el programa sometido a prueba.
IntelliTest usa el solucionador de restricciones Z3 .
Cobertura de código dinámico
Como efecto secundario de la supervisión en tiempo de ejecución, IntelliTest recopila datos dinámicos de cobertura de código. Esto se denomina dinámico porque IntelliTest solo conoce el código que se ha ejecutado, por lo tanto, no puede proporcionar valores absolutos para la cobertura de la misma manera que normalmente lo hacen otras herramientas de cobertura.
Por ejemplo, cuando IntelliTest informa de la cobertura dinámica como 5/10 bloques básicos, esto significa que se cubrieron cinco bloques de un total de diez, donde el número total de bloques en todos los métodos alcanzados hasta ahora por el análisis (en lugar de todos los métodos que existen en el ensamblado bajo prueba) es diez. Más adelante en el análisis, a medida que se detectan métodos más accesibles, tanto el numerador (5 en este ejemplo) como el denominador (10) pueden aumentar.
Enteros y flotantes
El solucionador de restricciones de IntelliTest determina los valores de entrada de prueba de tipos primitivos, como byte, int, float y otros, con el fin de desencadenar diferentes rutas de ejecución para la prueba y el programa sometido a prueba.
Objetos
IntelliTest puede crear instancias de clases de .NET existentes o puede usar IntelliTest para crear automáticamente objetos ficticios que implementen una interfaz específica y se comporten de maneras diferentes en función del uso.
Creación de instancias de clases existentes
¿Cuál es el problema?
IntelliTest supervisa las instrucciones ejecutadas cuando ejecuta una prueba y el programa sometido a prueba. En concreto, supervisa todo el acceso a los campos. A continuación, usa un solucionador de restricciones para determinar nuevas entradas de prueba, incluidos los objetos y sus valores de campo, de modo que la prueba y el programa sometido a prueba se comportarán de otras maneras interesantes.
Esto significa que IntelliTest debe crear objetos de determinados tipos y establecer sus valores de campo. Si la clase está visible y tiene un constructor predeterminado visible , IntelliTest puede crear una instancia de la clase . Si todos los campos de la clase están visibles, IntelliTest puede establecer los campos automáticamente.
Si el tipo no está visible o los campos no están visibles, IntelliTest necesita ayuda para crear objetos y ponerlos en estados interesantes para lograr una cobertura máxima de código. IntelliTest podría usar la reflexión para crear e inicializar instancias de maneras arbitrarias, pero esto no suele ser deseable porque podría traer el objeto a un estado que nunca puede producirse durante la ejecución normal del programa. En su lugar, IntelliTest se basa en sugerencias del usuario.
Visibilidad
.NET tiene un modelo de visibilidad elaborado: los tipos, métodos, campos y otros miembros pueden ser privados, públicos, internos, etc.
Cuando IntelliTest genera pruebas, intentará realizar solo acciones (como llamar a constructores, métodos y campos de configuración) que sean legales con respecto a las reglas de visibilidad de .NET desde el contexto de las pruebas generadas.
Las reglas son las siguientes:
Visibilidad de los miembros internos
- IntelliTest supone que las pruebas generadas tendrán acceso a los miembros internos que estaban visibles para la PexClass envolvente. .NET tiene InternalsVisibleToAttribute para ampliar la visibilidad de los miembros internos a otros ensamblajes.
Visibilidad de los miembros privados y familiares (protegidos en C#) de PexClass
- IntelliTest siempre coloca las pruebas generadas directamente en PexClass o en una subclase. Por lo tanto, IntelliTest supone que puede usar todos los miembros de la familia visibles (protegidos en C#).
- Si las pruebas generadas se colocan directamente en PexClass (normalmente mediante clases parciales), IntelliTest supone que también puede usar todos los miembros privados de PexClass.
Visibilidad de los miembros públicos
- IntelliTest supone que puede usar todos los miembros exportados visibles en el contexto de PexClass.
Simulacros con parámetros
¿Cómo probar un método que tiene un parámetro de un tipo de interfaz? ¿O de una clase no sellada? IntelliTest no sabe qué implementaciones se usarán más adelante cuando se llame a este método. Y quizás ni siquiera hay una implementación real disponible en tiempo de prueba.
La respuesta convencional consiste en usar objetos ficticios con comportamiento explícito.
Un objeto ficticio implementa una interfaz (o extiende una clase no sellada). No representa una implementación real, sino simplemente un acceso directo que permite la ejecución de pruebas mediante el objeto ficticio. Su comportamiento se define manualmente como parte de cada caso de prueba en el que se usa. Existen muchas herramientas que facilitan la definición de objetos ficticios y su comportamiento esperado, pero este comportamiento debe definirse manualmente.
En lugar de los valores codificados de forma rígida en objetos ficticios, IntelliTest puede generar los valores. Al igual que habilita las pruebas unitarias parametrizadas, IntelliTest también habilita los simulacros con parámetros.
Los simulacros con parámetros tienen dos modos de ejecución diferentes:
- Elección: al explorar el código, los simulacros parametrizados son una fuente de entradas de prueba adicionales y IntelliTest intentará elegir valores interesantes.
- reproducción: al ejecutar una prueba generada anteriormente, los simulacros parametrizados se comportan como códigos auxiliares con comportamiento (es decir, comportamiento predefinido).
Use PexChoose para obtener valores para los simulacros parametrizados.
Estructuras
El razonamiento de IntelliTest sobre los valores de estructura es similar a la forma en que se ocupa de los objetos.
Matrices y cadenas
IntelliTest supervisa las instrucciones ejecutadas a medida que ejecuta una prueba y el programa sometido a prueba. En concreto, observa cuándo el programa depende de la longitud de una cadena o una matriz (y los límites y longitudes inferiores de una matriz multidimensional). También observa cómo el programa usa los diferentes elementos de una cadena o matriz. A continuación, usa un solucionador de restricciones para determinar qué longitudes y valores de elemento pueden hacer que la prueba y el programa sometido a prueba se comporten de maneras interesantes.
IntelliTest intenta minimizar el tamaño de las matrices y cadenas necesarias para desencadenar comportamientos interesantes del programa.
Obtención de entradas adicionales
La clase estática PexChoose se puede usar para obtener entradas adicionales para una prueba y se puede usar para implementar simulacros parametrizados.
¿Tiene comentarios?
Publique sus ideas y solicitudes de características en la Comunidad de desarrolladores.