2010-01-01 7 views
100

Je viens de commencer avec F #, qui est mon premier langage fonctionnel. J'ai travaillé presque exclusivement avec C#, et j'aime beaucoup comment F # m'amène à repenser la façon dont j'écris le code. Un aspect que je trouve un peu désorientant est le changement dans le processus d'écriture du code. J'utilise TDD depuis des années en C# et j'apprécie vraiment d'avoir des tests unitaires pour savoir où je suis. Jusqu'ici, mon processus avec F # a été d'écrire certaines fonctions, de jouer avec eux avec la console interactive jusqu'à ce que je sois "raisonnablement" sûr qu'ils fonctionnent, et de modifier & combiner. Cela fonctionne bien sur des problèmes à petite échelle comme le projet Euler, mais je ne peux pas imaginer construire quelque chose de cette façon.Développement F # et tests unitaires?

Comment les gens abordent-ils les tests unitaires et la construction d'une suite de tests pour un programme F #? Y a-t-il un équivalent à TDD? Tout pointeur ou pensée est apprécié.

+1

http://www.expert-fsharp.com/CodeSamples/Forms/AllItems.aspx?RootFolder=%2fCodeSamples%2fChapter18%2fExample06 montre un exemple simple d'utilisation NUnit avec F #. – itowlson

+0

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

+0

connexes: http://stackoverflow.com/questions/5667372/what-unit-testing-frameworks- are-available-for-f/5669263 # 5669263 (Unquote est beaucoup plus qu'une note de bas de page/commentaire car il est dans le answeret sur cette page) –

Répondre

71

Les développeurs pilotés par les tests devraient se sentir comme chez eux dans les langages fonctionnels comme F #: les petites fonctions qui donnent des résultats déterministes et reproductibles se prêtent parfaitement aux tests unitaires. Il y a aussi des capacités dans le langage F # qui facilitent les tests d'écriture. Prenez, par exemple, Object Expressions. Vous pouvez très facilement écrire des faux pour des fonctions qui prennent comme entrée un type d'interface. Si quelque chose, F # est un langage orienté objet de première classe et vous pouvez utiliser les mêmes outils et astuces que vous utilisez lorsque vous faites TDD en C#. Il y a aussi quelques outils de tests écrits ou spécifiquement pour F #:

Matthew Podwysocki a écrit un grand series sur les tests unitaires dans les langages fonctionnels . Oncle Bob a également écrit un article provoquant la réflexion here.

+9

J'ai également développé (et je développe activement) une bibliothèque de tests unitaires spécifiques à F # appelée Unquote: http://code.google.com/p/unquote/. Il vous permet d'écrire des assertions de test sous la forme d'expressions booléennes F #, vérifiées statiquement, en utilisant F # Quotations et produit automatiquement de bons messages d'échec de test. Il fonctionne sans configuration avec un support spécial à la fois pour xUnit.net et NUnit et prend généralement en charge toute structure de test unitaire basée sur les exceptions. Il fonctionne même au sein de sessions FSI permettant une migration transparente des tests interactifs aux suites de tests formels. –

+0

Il y a aussi [Pex] (http://www.pexforfun.com/), mais c'est un peu plus difficile à trouver. – Benjol

+0

Uncle bob link semble mort – bump

6

Vous pourriez jeter un oeil à FSUnit - bien que je ne l'ai pas encore utilisé, il pourrait valoir la peine d'essayer. Certainement mieux que d'utiliser par exemple NUnit (natif) en F #.

+1

ShdNx, pourquoi recommanderiez-vous contre NUnit? Le livre F # de Don Syme montre NUnit pour les tests et il semble assez similaire à l'utilisation de NUnit en C#. Le FSUnit DSL a l'air cool, mais pour les personnes déjà familières avec NUnit (Mathias utilise "TDD depuis des années") est-ce votre expérience que l'utilisation de NUnit avec F # est plus problématique qu'avec C# ou VB? – itowlson

+0

Je deuxième commentaire itowlson, et question. Certainement NUnit en F # semble assez étrange, mais à part ça, êtes-vous conscient des problèmes spécifiques qui font que c'est une bonne idée d'utiliser autre chose? – Mathias

+1

Je dirais que "regarder assez étrange" est généralement une raison impérieuse de trouver quelque chose de mieux. Regarder étrange signifie difficile à lire, et difficile à lire signifie des bugs. (Je suppose que "regarder bizarre" est complètement différent de "regarder nouveau et/ou inconnu" - familier deviendra familier, étrange restera étrange.) –

10

Je pense que c'est une question très intéressante que je me suis beaucoup posée moi-même. Mes pensées jusqu'à présent ne sont que des pensées, alors prenez-les pour ce qu'elles sont. Je pense que le filet de sécurité d'une suite de tests automatisés est un atout trop précieux pour être lâché, quelle que soit la séduction de cette console interactive, alors je prévois de continuer à écrire des tests unitaires comme je l'ai toujours fait.

L'une des principales forces de .NET réside dans ses capacités multilingues. Je sais que je vais bientôt écrire du code de production F #, mais mon plan est d'écrire des tests unitaires en C# pour faciliter mon chemin vers ce qui est pour moi une nouvelle langue. De cette façon, je peux aussi tester que ce que j'écris en F # sera compatible avec C# (et d'autres langages .NET). Avec cette approche, je comprends qu'il y a certaines fonctionnalités de F # que je peux seulement utiliser en interne dans mon code F #, mais pas d'exposer dans le cadre de mon API publique, mais je vais accepter cela, tout comme je l'accepte aujourd'hui il y a certaines choses que C# me permet d'exprimer (comme uint) qui ne sont pas conformes CLS, et donc je m'abstiens de les utiliser.

+1

Comment allait votre plan? Il était facile de tester le code f # avec le code C#? J'ai commencé à apprendre f # et mon plan est d'écrire une partie de mon projet en f # et j'ai la même idée: écrire des tests unitaires en C# pour f # aussi. –

+0

@Marquez-vous des mises à jour? J'ai aussi du mal à entrer dans le flux en utilisant TDD avec F #. –

+1

@ScottNimrod Quelques mises à jour: quatre de [mes cours Pluralsight] (http://bit.ly/ploehralsight) concernent les tests ou TDD avec F #. Vous trouverez également de nombreux enregistrements gratuits des conférences sur [mon profil Lanyrd] (http://lanyrd.com/profile/ploeh).Enfin, il y a [mon blog] (http://blog.ploeh.dk). –

14

Jetez un oeil à FsCheck, un outil de test automatique pour F #, est essentiellement un port de QuickCheck Haskell. Il vous permet de fournir une spécification de le programme, sous la forme de propriétés que les fonctions ou les méthodes devraient satisfaire , et les tests FsCheck que les propriétés contiennent dans un grand nombre de cas générés de manière aléatoire.

FsCheck CodePlex Page

FsCheck Author Page

+0

Oui, je pense que FsCheck offre beaucoup plus que les frameworks de tests unitaires traditionnels tels que NUnit etc. – Robert

21

J'utilise NUnit, et il ne me semble pas difficile à lire ou à titre onéreux d'écrire:

open NUnit.Framework 

[<TestFixture>] 
type myFixture() = class 

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

end 

Depuis mon code est un mélange de F # et D'autres langues .Net, j'aime le fait que j'écris les tests unitaires de la même façon et avec une syntaxe similaire en F # et en C#.

+4

Après avoir lu d'autres réponses ici, j'ai essayé FSUnit, et je pense que c'est génial. Cela fonctionne bien avec TestDriven.Net (comme le fait NUnit), encourage un style fluide d'écriture de tests auto-documentés et, comme l'indique Ray, est "plus à l'aise dans les langages F #". Pas mal pour 21 lignes de code! (Et quelques recommandations de mise en page/nommage). Deux notes rapides: 1. La DLL FSUnit précompilée ne fonctionnait pas pour moi. Construire à partir de la source (FsUnit.NUnit-0.9.0.fs) a résolu le problème. 2. TestDriven.Net ne reconnaît pas les noms de TextFixture qui ressemblent à '\' comme ceci \ ''. Les noms de test utilisant un double tick sont reconnus. –

10

Comme dglaubman suggère que vous pouvez utiliser NUnit. xUnit.net fournit également un support pour cela et fonctionne bien avec TestDriven.net. Le code ressemble à des tests NUnit mais sans l'obligation d'encapsuler le test dans un type conteneur.

#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, les nouvelles surcharges de Xunit semblent causer des ravages avec mon F #. –

+0

@RickMinerich J'ai vécu la même chose qui arrive à mon code. J'ai juste fini par ajouter des annotations de type explicites afin que la surcharge correcte soit choisie. Cependant, cela * ajoute * plus de bruit à votre code malheureusement. –