2010-01-01 23 views
100

Acabo de empezar con F #, que es mi primer lenguaje funcional. He estado trabajando casi exclusivamente con C#, y disfruto mucho de cómo F # me lleva a volver a pensar cómo escribo el código. Un aspecto que encuentro un poco desorientador es el cambio en el proceso de escribir código. He estado usando TDD durante años en C# ahora, y realmente aprecio tener pruebas unitarias para saber dónde estoy.F # desarrollo y pruebas unitarias?

Hasta ahora, mi proceso con F # ha sido escribir algunas funciones, jugar con ellas con la consola interactiva hasta que esté "razonablemente" seguro de que funcionan, y ajustar & combinar. Esto funciona bien en problemas de pequeña escala como el Proyecto Euler, pero no puedo imaginar construir algo grande de esa manera.

¿Cómo se acercan las personas a las pruebas unitarias y crean un conjunto de pruebas para un programa F #? ¿Hay un equivalente a TDD? Cualquier punteros o pensamientos son apreciados.

+1

http://www.expert-fsharp.com/CodeSamples/Forms/AllItems.aspx?RootFolder=%2fCodeSamples%2fChapter18%2fExample06 muestra un ejemplo sencillo de utilizar NUnit con F #. – itowlson

+0

ver http://stackoverflow.com/questions/1468772/how-to-handle-unit-tests-in-f –

+0

relacionado: http://stackoverflow.com/questions/5667372/what-unit-testing-frameworks- are-available-for-f/5669263 # 5669263 (Unquote es mucho más que una nota al pie/comentario ya que está dentro del conjunto de respuestas en esta página) –

Respuesta

71

Los desarrolladores basados ​​en pruebas deben sentirse como en casa en lenguajes funcionales como F #: las funciones pequeñas que dan resultados determinísticamente repetibles se prestan perfectamente a las pruebas unitarias. También hay capacidades en el lenguaje F # que facilitan las pruebas de escritura. Tome, por ejemplo, Object Expressions. Puede escribir fácilmente falsificaciones para funciones que toman como entrada un tipo de interfaz.

En todo caso, F # es un lenguaje orientado a objetos de primera clase y puede utilizar las mismas herramientas y trucos que utiliza al hacer TDD en C#. También hay algunas herramientas de pruebas escritas en o específicamente para F #:

Mateo Podwysocki escribió un gran series en la unidad de pruebas en los lenguajes funcionales . Tío Bob también escribió un artículo que invita a la reflexión here.

+9

También desarrollé (y estoy desarrollando activamente) una biblioteca de pruebas de unidades específicas de F # llamada Unquote: http://code.google.com/p/unquote/. Le permite escribir afirmaciones de prueba como expresiones booleanas F # sencillas y estáticamente comprobadas utilizando citas de F # y produce automáticamente buenos mensajes de error de prueba. Funciona sin configuración con soporte especial para xUnit.net y NUnit y generalmente admite cualquier marco de prueba de unidades basado en excepciones. Incluso funciona dentro de las sesiones de FSI, lo que permite una migración sin inconvenientes desde pruebas interactivas a conjuntos de pruebas formales. –

+0

También hay [Pex] (http://www.pexforfun.com/), aunque eso es un poco más difícil de asimilar. – Benjol

+0

El vínculo del tío bob parece estar muerto – bump

6

Podrías echar un vistazo a FSUnit - aunque aún no lo he usado, podría valer la pena intentarlo. Ciertamente mejor que usar, por ejemplo, NUnit (nativo) en F #.

+1

ShdNx, por qué recomendarías contra NUnit? El libro F # de Don Syme muestra NUnit para probar y parece bastante similar al uso de NUnit en C#. El FSUnit DSL parece genial, pero para las personas que ya están familiarizadas con NUnit (Mathias ha "estado usando TDD durante años") ¿es su experiencia que usar NUnit con F # es más problemático que con C# o VB? – itowlson

+0

I segundo comentario de itowlson y pregunta. Definitivamente NUnit en F # parece bastante extraño, pero además de eso, ¿conoces problemas específicos que hacen que sea una buena idea usar algo más? – Mathias

+1

Diría que "parecer bastante extraño" suele ser una razón de peso para encontrar algo mejor. Buscar extraño significa difícil de leer, y difícil de leer significa errores. (asumo que "parecer extraño" es completamente diferente a "parecer nuevo y/o no familiar"; lo desconocido se volverá familiar, extraño se mantendrá extraño.) –

10

Creo que esta es una pregunta muy interesante que me he preguntado mucho. Mis pensamientos hasta ahora son solo pensamientos, así que tómelos como lo que son.

Creo que la red de seguridad de un conjunto de pruebas automatizado es un activo demasiado valioso para dejarlo ir, por atractiva que sea la consola interactiva, así que planeo continuar escribiendo pruebas de unidad como siempre lo he hecho.

Una de las principales fortalezas de .NET son las capacidades de idiomas cruzados. Sé que voy a escribir código de producción de F # pronto, pero mi plan es escribir pruebas de unidad en C# para abrirme paso en lo que para mí es un nuevo idioma. De esta forma, también puedo probar que lo que escribo en F # será compatible con C# (y otros lenguajes .NET).

Con este enfoque, entiendo que hay ciertas características de F # que solo puedo usar internamente en mi código F #, pero no las expongo como parte de mi API pública, pero lo aceptaré, tal como lo acepto hoy. hay ciertas cosas que C# me permite expresar (como uint) que no cumplen con CLS, por lo que me abstengo de usarlas.

+1

¿Cómo iba tu plan? ¿Fue fácil probar el código f # con el código C#? Comencé a aprender f # y mi plan es escribir una parte de mi proyecto en f # y tengo la misma idea: escribir pruebas unitarias en C# para f # también. –

+0

@Mark ¿Alguna actualización? También estoy teniendo dificultades para entrar en flujo usando TDD con F #. –

+1

@ScottNimrod Bastantes actualizaciones: cuatro de [mis cursos Pluralsight] (http://bit.ly/ploehralsight) tratan sobre pruebas o TDD con F #. También encontrarás muchas grabaciones gratuitas de conferencias en [mi perfil de Lanyrd] (http://lanyrd.com/profile/ploeh).Finalmente, está [mi blog] (http://blog.ploeh.dk). –

14

Tenga una mirada en fscheck, una herramienta de prueba automática para F #, es básicamente un puerto de QuickCheck de Haskell. Le permite proporcionar una especificación del programa , en forma de propiedades que las funciones o métodos deben cumplir , y FsCheck prueba que las propiedades se mantienen en un gran número de casos generados aleatoriamente .

FsCheck CodePlex Page

FsCheck Author Page

+0

Sí, creo que FsCheck ofrece mucho más que los marcos de pruebas unitarias tradicionales como NUnit, etc. – Robert

21

utilizo NUnit, y no me parece que sea difícil de leer o onerosa para escribir:

open NUnit.Framework 

[<TestFixture>] 
type myFixture() = class 

    [<Test>] 
    member self.myTest() = 
     //test code 

end 

Desde mi código es una mezcla de F # y otros lenguajes .Net, me gusta el hecho de que escribo las pruebas unitarias básicamente de la misma manera y con una sintaxis similar tanto en F # como en C#.

+4

Después de leer otras respuestas aquí, le di una oportunidad a FSUnit, y creo que es genial. Funciona bien con TestDriven.Net (al igual que NUnit), fomenta un estilo fluido de escritura de pruebas autodocumentadas y, como dice Ray, es "más familiar en los lenguajes F #". ¡No está mal para 21 líneas de código! (Y un par de recomendaciones de diseño/nomenclatura). Dos notas rápidas: 1. La DLL FSUnit precompilada no me funcionaba. La construcción desde la fuente (FsUnit.NUnit-0.9.0.fs) solucionó el problema. 2. TestDriven.Net no reconoce los nombres de TextFixture que parecen '\' como este \ ''. Se reconocen los nombres de prueba usando la forma de doble tilde. –

10

Como dglaubman sugiere que puede usar NUnit. xUnit.net también proporciona soporte para esto y funciona bien con TestDriven.net. El código es similar a las pruebas de NUnit pero sin el requisito de ajustar la prueba en un tipo contenedor.

#light 

// Supply a module name here not a combination of module and namespace, otherwise 
// F# cannot resolve individual tests nfrom the UI. 
module NBody.DomainModel.FSharp.Tests 

open System 
open Xunit 

open Internal 

[<Fact>] 
let CreateOctantBoundaryReordersMinMax() = 
    let Max = VectorFloat(1.0, 1.0, 1.0) 
    let Min = VectorFloat(-1.0, -1.0, -1.0) 

    let result = OctantBoundary.create Min Max 

    Assert.Equal(Min, result.Min)  
    Assert.Equal(Max, result.Max) 
+0

A partir de 1.9.1, las nuevas sobrecargas de Xunit parecen estar causando estragos en mi F #. –

+0

@RickMinerich He experimentado lo mismo que sucede con mi código. Acabo de agregar anotaciones de tipo explícito para elegir la sobrecarga correcta. Sin embargo, esto * * agrega más ruido a su código desafortunadamente. –