Logotipo para GIGAOM 365x70

Vea qué solución de pruebas de API resultó ganadora en el informe GigaOm Radar. Obtenga su informe analítico gratuito >>

Cumplimiento de software DO-178C para la industria aeroespacial y de defensa

Cobertura del código estructural

Recolectando y analizando métricas de cobertura de código es un aspecto importante del desarrollo de software crítico para la seguridad. La cobertura de código mide la finalización de los casos de prueba y las pruebas ejecutadas. Proporciona evidencia de que la verificación está completa, al menos según lo especificado por el diseño del software. Los objetivos del análisis de cobertura de prueba incluyen lograr los siguientes objetivos de cobertura de prueba:

Círculo azul con un icono de una marca de verificación blanca en el centro.

Requisitos de alto nivel

Círculo azul con un icono de una marca de verificación blanca en el centro.

Requisitos de bajo nivel

Círculo azul con un icono de una marca de verificación blanca en el centro.

Estructura del software según los criterios de cobertura adecuados

Círculo azul con un icono de una marca de verificación blanca en el centro.

Estructura del software, tanto acoplamiento de datos como acoplamiento de control

Icono dentro de un círculo azul que muestra un contorno blanco de una lista de verificación de pautas.

Sección 6.4.4.1

La sección 178 de DO-6.4.4.1C cubre el análisis de cobertura de las pruebas de requisitos, que determina qué tan bien las pruebas funcionales han verificado la implementación de los requisitos. Se espera que el análisis de cobertura de código se recopile durante estas pruebas y que las brechas restantes en la cobertura de código se cierren con pruebas adicionales.

Icono dentro de un círculo azul que muestra un contorno blanco de una lista de verificación de pautas.

Sección 6.4.4.2

La sección 6.4.4.2 exige un análisis para determinar lo que queda de la cobertura del código, incluidas las interfaces entre los componentes. La sección 6.4.4.3 describe los requisitos para resolver cualquiera de las brechas en la cobertura, incluida la identificación de código extraño, inactivo y desactivado.

La forma en que esto se traduce en tipos y cantidades de cobertura es algo que está abierto a la interpretación. Sin embargo, en el desarrollo de software aeronáutico, la responsabilidad de planificar la cobertura del código, cumplir con el plan, documentarlo y completarlo recae en el fabricante.

Tipos de cobertura de código

A continuación se muestran los diferentes tipos de cobertura de código.

Cobertura de estados de cuenta

La cobertura de declaraciones requiere que cada declaración del programa se ejecute al menos una vez. La cobertura de sucursales y MC/DC abarca la cobertura de declaraciones.

Cobertura de sucursales

La cobertura de rama garantiza que se ejecute cada rama de decisión (construcciones if-then-else).

Cobertura por decisión o condición modificada (MC/DC)

La cobertura de decisión/condición modificada (MC/DC) requiere la cobertura de código más completa para garantizar que los casos de prueba ejecuten cada rama de decisión y todas las combinaciones posibles de entradas que afectan el resultado de la lógica de decisión. En el caso de la lógica compleja, la cantidad de casos de prueba puede explotar, por lo que las restricciones de condición modificada se utilizan para limitar los casos de prueba a aquellos que dan como resultado expresiones lógicas independientes que cambian.

Código ejecutable/objeto

Se requiere código ejecutable/objeto si el criterio de nivel de software es A. Esto se debe al hecho de que un compilador o enlazador genera código ensamblador adicional que no se puede rastrear directamente hasta las declaraciones del código fuente. Por lo tanto, se debe realizar una cobertura a nivel de objeto.

Avanzado herramientas de automatización de pruebas unitarias, como Parasoft C/C++test, proporciona todas estas métricas de cobertura de código y más. C/C++test CT también automatiza esta recopilación de datos en las pruebas del host y del destino y acumula un historial de cobertura de pruebas a lo largo del tiempo. Este historial de cobertura de código puede abarcar pruebas unitarias, de integración y del sistema para garantizar que la cobertura sea completa y rastreable en todos los niveles de prueba.

Fotografía que muestra un primer plano de la cabina de un transbordador espacial.

Cobertura de las pruebas del sistema

Obtener cobertura de código mediante pruebas del sistema es un método excelente para determinar si se han realizado suficientes pruebas. El enfoque consiste en ejecutar todas las pruebas del sistema y luego examinar qué partes del código no se han probado.

El código no ejecutado implica que puede haber necesidad de nuevos casos de prueba para ejercitar el código intacto donde puede estar oculto un defecto y ayuda a responder la pregunta: ¿He realizado suficientes pruebas?

Cuando los equipos realizan pruebas del sistema, la métrica resultante promedio es de una cobertura del 60 %. Gran parte del 40 % de código no ejecutado se debe al código defensivo de su aplicación. El código defensivo solo se ejecuta cuando el sistema activa una falla o entra en un estado problemático que puede ser difícil de producir. Las condiciones como la pérdida de memoria u otros tipos de fallas causadas por fallas de hardware pueden tardar semanas, meses o años en detectarse.

También existe un código defensivo que exigen las pautas de codificación y que nunca se puede ejecutar con los casos de prueba del sistema. Por estos motivos, las pruebas del sistema no pueden llevarte a una cobertura del código estructural del 100 %. Deberás emplear otros métodos de prueba, como pruebas manuales o unitarias, para alcanzar el 100 %.

Cobertura de las pruebas unitarias

Como se mencionó, las pruebas unitarias se pueden utilizar como un enfoque complementario a las pruebas del sistema para obtener una cobertura del 100%. Obtener cobertura de código a través de pruebas unitarias es uno de los métodos más populares, pero no revela si ha realizado suficientes pruebas del sistema porque el enfoque está en el nivel de unidad (función/procedimiento).

El objetivo aquí es crear un conjunto de casos de prueba unitaria que ejerciten toda la unidad en la necesidad de cobertura requerida (declaración, rama y MC/DC) para alcanzar una cobertura del 100 % para esa unidad individual. Esto se repite para cada unidad hasta que se cubra toda la base de código. Sin embargo, para aprovechar al máximo las pruebas unitarias, no se concentre únicamente en obtener cobertura de código. Esto generalmente se puede lograr a través de casos de prueba de escenarios de días soleados.

Ponga a prueba la unidad en situaciones de días soleados y lluviosos para garantizar la solidez, la seguridad y la trazabilidad de los requisitos de bajo nivel. Deje que la cobertura del código sea un subproducto de sus casos de prueba y complete la cobertura donde sea necesario.

Para acelerar la cobertura del código mediante pruebas unitarias, existen capacidades de generación de casos de prueba configurables y automatizadas en Parasoft C/C++test. Los casos de prueba se pueden generar automáticamente para probar el uso de punteros nulos, rangos mínimo-medio-máximo, valores límite y mucho más. Esta automatización puede llevarlo lejos. En minutos, obtendrá una cantidad sustancial de cobertura de código.

Captura de pantalla del código para una declaración de retorno 0 inalcanzable
Declaración de retorno inalcanzable 0;

Además, C/C++test CT amplía los flujos de trabajo de desarrollo con cobertura de código al integrarse con marcos de pruebas unitarias y entornos de desarrollo integrados (IDE) propietarios. Integre estrechamente la cobertura de código de línea, declaración, condición simple, decisión, rama, función, llamada y MC/DC con marcos de pruebas unitarias propietarios como GoogleTest y CppUnit e IDE como VS Code.

Sin embargo, como en las pruebas de sistemas, obtener una cobertura de código del 100 % es difícil debido al uso de código defensivo o semántica de lenguaje formal. En el nivel granular de una unidad, el código defensivo puede presentarse en forma de una declaración predeterminada en un conmutador. Si se capturan todos los casos posibles en un conmutador, la declaración predeterminada queda inalcanzable. En el ejemplo siguiente, el retorno 0; nunca se ejecutará porque el while (1) es infinito.

¿Cómo obtener una cobertura del 100% para estos casos especiales?

Respuesta: Implementar métodos manuales.

Sigue estos pasos.

  1. Etiquete o anote la declaración como cubierta mediante el uso de un depurador.
  2. Modifique la pila de llamadas y ejecute la instrucción return 0;.
  3. Sea testigo visual de la ejecución y, como mínimo, documente el nombre del archivo, la línea de código y la declaración de código que ahora se considera cubierta.

Esta cobertura realizada mediante inspección manual/visual e informes se puede utilizar para complementar la cobertura capturada mediante pruebas unitarias. La adición de ambos informes de cobertura se puede utilizar para demostrar una cobertura del código estructural del 100%.

El objetivo de obtener cobertura de código es un medio adicional para ayudar a garantizar la seguridad, protección y confiabilidad del código.

Instrumentación de código

La cobertura del código se identifica, en la mayoría de los casos, por tener el código instrumentado. Instrumentado se refiere a tener el código de usuario adornado con código adicional para determinar durante la ejecución si esa instrucción, rama o MC/CD se ha ejecutado.

Dependiendo del objetivo o sistema bajo prueba, los datos de cobertura se pueden almacenar en el sistema de archivos, escribir en la memoria o enviar a través de varios canales de comunicación, como el puerto serie, el puerto TCP/IP, USB e incluso JTAG.

Instrumentación parcial

Tenga en cuenta que la instrumentación del código provoca un exceso de código. El aumento del tamaño del código puede afectar la capacidad de cargar el código en el hardware de destino con limitaciones de memoria para realizar pruebas.

La solución alternativa es instrumentar parte del código siguiendo estos pasos:

  1. Ejecute sus pruebas y capture la cobertura.
  2. Instrumentar la otra parte del código.
  3. Ejecute sus pruebas de nuevo.
  4. Captura la cobertura.
  5. Fusionar la cobertura de la ejecución de prueba anterior.

Asesor de cobertura

Parasoft C/C++test resuelve las brechas de cobertura en los conjuntos de pruebas. Parasoft descubrió cómo utilizar el análisis de código estático avanzado (análisis de flujo de datos y control) para encontrar valores para los parámetros de entrada necesarios para ejecutar líneas específicas de código no cubierto.

En los códigos complejos, siempre hay esas declaraciones de código elusivas para las que es extremadamente difícil obtener cobertura. Es probable que haya múltiples valores de entrada con varias permutaciones y rutas posibles que hacen que descifrarlas sea una tarea enrevesada y que lleve mucho tiempo. Pero solo una combinación puede brindarle la cobertura que necesita. Parasoft facilita la obtención de cobertura de esas líneas de código difíciles de alcanzar.

Cuando selecciona la línea de código que desea cubrir, el Asesor de Cobertura le indicará qué valores de entrada, variables globales y llamadas externas necesita para estimular el código y obtener cobertura.

Captura de pantalla del Asesor de cobertura de pruebas Parasoft C/C++.
Invocar el Asesor de Cobertura haciendo clic derecho en la línea de código.
Captura de pantalla que muestra dos soluciones de casos de prueba proporcionadas por Coverage Advisor en C/C++test.
Dos soluciones de casos de prueba proporcionadas por Coverage Advisor.

La figura de la derecha muestra un informe de análisis que proporciona al usuario una solución. El campo Condiciones previas expresa:

  • El rango y los valores de entrada para mainSensorSignal y coSensorSignal
  • Los resultados esperados de las llamadas externas

Al crear el caso de prueba unitario con estos valores de parámetros establecidos y stubs para llamadas externas, obtiene cobertura de la línea seleccionada, más las líneas adicionales expresadas en el campo Cobertura esperada.


Cobertura de código de objeto

Captura de pantalla de Parasoft ASMTool para la cobertura de código objeto/ensamblador
Parasoft ASMTool para la cobertura de código objeto/ensamblador

Para las aplicaciones más exigentes y críticas para la seguridad, se requiere la cobertura de código de objeto DO-178C Nivel A. Por lo tanto, se debe realizar una cobertura a nivel de ensamblaje. Imagine el rigor y el costo de mano de obra que implicaría tener que realizar esta tarea. Afortunadamente, Parasoft ASMTools ofrece una solución automatizada para obtener la cobertura de código de objeto.

Pancarta azul oscuro con imagen de un hombre hablando con una mujer sosteniendo una tableta en la mano en una sala de servidores.
Imagen de un hombre y una mujer con una tableta en la mano conversando en una sala de servidores.

Mejore sus pruebas de software con las soluciones de Parasoft.