2012-04-02 18 views
7

Tengo un número de módulos de "biblioteca" en OCaml (principalmente funciones de utilidad y auxiliar) donde agregué el siguiente tipo de código al final para pruebas de unidades triviales:múltiples "líneas principales" en módulos OCaml vinculados

let main() = ... 
main 

o

let() = ... 

Este código ser que principalmente se imprime en la consola (para propósitos de prueba simples). El problema ahora es que cuando enlace mis módulos de "biblioteca" con mi módulo "principal" y ejecuto el programa, recibo todos estos mensajes de prueba que me distraen. ¿Hay alguna manera de incluir código en un módulo OCaml que se ejecuta cuando el módulo está vinculado solo (lo que facilita las pruebas triviales) pero no cuando se usa como una "biblioteca"? He leído publicaciones en SO en el sentido de que OCaml no tiene ninguna noción de un módulo "principal" y que todos los módulos son iguales, sin embargo, me parece que el orden de los archivos objeto entregados al enlazador podría interpretarse como indicador de que el el último módulo es el "principal" (ya que está en la parte superior de la "cadena alimentaria de dependencia").

Respuesta

7

OCaml admite enlaces estáticos y carga dinámica de módulos; lo que normalmente hace (y lo que es seguro) es la vinculación estática. Solo recomendaría la carga dinámica si necesita algún tipo de arquitectura de complemento.

De todos modos, una biblioteca no es más que un módulo (probablemente con submódulos). Si enlaza estáticamente un módulo, todas las rutinas "principales" se ejecutarán en el orden de los módulos que están vinculados en su ejecutable.

Así que si no haces nada al respecto, un módulo no sabe en qué ejecutable se está vinculando de alguna manera "mágica"; lo que debe hacer es mi humilde opinión:

  • mover las pruebas fuera de los módulos, tal vez usando ounit O
  • al menos reescribir sus funciones de prueba que son funciones reales, por ejemplo "let test() = ..."; luego, escriba una interfaz de prueba que llamará a todas las funciones de "prueba" de todos sus módulos.

adición:

Si lo hace en otros idiomas, no parece haber ninguna torta libre, ya sea:

En Java que si tiene varias de red en el código, de forma explícita debe seleccione el que desea que se ejecute el ejecutable.

En C se puede utilizar el preprocesador de C para hacer algo como

#ifdef TEST_1 
int main() { 
... 
} 
#endif 

OCaml tiene su propio preprocesador camlp4 (camlp4 wikipedia article) con la que se podría hacer algo similar. Personalmente considero este tipo de incrustación de prueba como una mala ingeniería de software. Debería probar su módulo/clase/... desde el lado de la interfaz y marcar sus invariantes internas con aserciones (que existen en Java, C & OCaml).

+0

En C tienes razón, necesitarías usar una interfaz de prueba, pero en Java es una práctica común para cada clase no trivial tener un main() haciendo algún tipo de "prueba" superficial: cuando te mueves a un marco de prueba que ese tipo de código se limpia y no tiene otro propósito, pero durante el desarrollo activo inicial esta instalación tiene su uso. Me doy cuenta de que en OCaml tienes el toplevel, pero no es lo mismo. –

+0

comment: see addéndum – lambdapower

5

La cadena de herramientas no tiene ninguna provisión para esto, genera un archivo que ejecuta el código de nivel superior de todos los módulos al inicio, en orden de vinculación.

No veo cómo hacerlo funcionar sistemáticamente. Los módulos casi siempre tienen algún código de nivel superior que necesita ser ejecutado. Necesitaría una manera de separar el código de nivel superior en dos grupos (un grupo siempre se ejecuta, el otro solo se ejecuta cuando el módulo es el último en vincularse). Esto parece innecesariamente desordenado.

Una mejor solución (me parece) es utilizar un marco de prueba un poco más sofisticado.

Cuestiones relacionadas