F # geliştirme ve birim testi?


107

İlk işlevsel dilim olan F # ile yeni başladım. Yarı-sadece C # ile çalışıyorum ve F # 'ın beni nasıl kod yazacağımı yeniden düşünmeye yönlendirdiği çok hoşuma gidiyor. Biraz kafa karıştırıcı bulduğum bir yön, kod yazma sürecindeki değişiklik. TDD'yi yıllardır C # ile kullanıyorum ve nerede olduğumu bilmek için birim testlere sahip olduğum için gerçekten minnettarım.

Şimdiye kadar, F # ile sürecim, bazı işlevler yazmak, çalıştıklarından "makul ölçüde" emin olana kadar etkileşimli konsolla oynamak ve ince ayar yapmak ve birleştirmek oldu. Bu, Euler Projesi gibi küçük ölçekli problemlerde işe yarar, ancak bu şekilde büyük bir şey inşa etmeyi hayal edemiyorum.

İnsanlar birim testine ve bir F # programı için bir test paketi oluşturmaya nasıl yaklaşıyor? TDD'nin bir eşdeğeri var mı? Herhangi bir işaret veya düşünce takdir edilir.


1
expert-fsharp.com/CodeSamples/Forms/… , NUnit'i F # ile kullanmanın basit bir örneğini gösterir.
itowlson


related: stackoverflow.com/questions/5667372/… (Alıntı, bu sayfadaki cevap setinde olduğu için bir dipnot / yorumdan çok daha fazlasıdır)
Ruben Bartelink

Bu yanıtlarda eksik olan bir şey, F # 'ın tür çıkarımına bağlı olan Foq, AutoFixture.AutoFoq ve AutoFixture.xUnit'in uygun bir örneğidir. Tadım için trelford.com/blog/post/test5.aspx ve trelford.com/blog/post/fstestlang.aspx sayfasına bakın ve bir gün buraya uygun bir cevap yazacağım
Ruben Bartelink

Yanıtlar:


77

Test odaklı geliştiriciler F # gibi işlevsel dillerde kendilerini evlerinde hissetmelidir: deterministik olarak tekrarlanabilir sonuçlar veren küçük işlevler, birim testlerine mükemmel bir şekilde katkıda bulunur. F # dilinde yazma testlerini kolaylaştıran yetenekler de vardır. Örneğin, Nesne İfadelerini ele alalım . Girdi olarak bir arabirim türü alan işlevler için kolayca sahte yazabilirsiniz.

Bir şey varsa, F # birinci sınıf bir nesne yönelimli dildir ve C # ile TDD yaparken kullandığınız aynı araçları ve püf noktalarını kullanabilirsiniz. Ayrıca, özellikle F # için yazılmış bazı test araçları da vardır:

Matthew Podwysocki , fonksiyonel dillerde birim testi üzerine harika bir dizi yazdı . Bob Amca da burada düşündürücü bir makale yazdı .


9
Ayrıca Unquote: code.google.com/p/unquote adında bir F # özel birim test kitaplığı geliştirdim (ve aktif olarak geliştiriyorum) . Test iddialarını F # Quotations kullanarak düz, statik olarak kontrol edilen F # boole ifadeleri olarak yazmanıza olanak tanır ve otomatik olarak güzel test hatası mesajları üretir. Hem xUnit.net hem de NUnit için özel destekle konfigürasyonsuz çalışır ve genellikle istisnalara dayalı birim testi çerçevesini destekler. Hatta FSI oturumlarında çalışır ve etkileşimli testlerden resmi test paketlerine sorunsuz geçiş sağlar.
Stephen Swensen

Orada Pex bu biraz daha zor grok olsa da.
Benjol

1
Bob Amca Bağlantısı Ölü
Görünüyor

22

NUnit kullanıyorum ve okuması ya da yazması o kadar zor olmuyor:

open NUnit.Framework

[<TestFixture>]
type myFixture() = class

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

end

Kodum F # ve diğer .Net dillerinin bir karışımı olduğu için, birim testlerini temelde aynı şekilde ve hem F # hem de C # ile benzer sözdizimiyle yazmam hoşuma gidiyor.


4
Burada diğer yanıtları okuduktan sonra FSUnit'e bir şans verdim ve bence harika. TestDriven.Net ile iyi çalışır (NUnit gibi), kendi kendini belgeleyen testleri yazmanın akışkan bir tarzını teşvik eder ve Ray'in de belirttiği gibi, "F # dillerinde daha çok evde" dir. 21 satır kod için fena değil! (Ve birkaç düzen / adlandırma önerisi). İki hızlı not: 1. Önceden derlenmiş FSUnit DLL benim için çalışmadı. Kaynaktan (FsUnit.NUnit-0.9.0.fs) derleme sorunu çözdü. 2. TestDriven.Net, görünen TextFixture adlarını tanımıyor `like this`. Çift tik formu kullanan test isimleri tanınır.
David Glaubman

15

F # için otomatik bir test aracı olan FsCheck'e bir göz atın , temelde Haskell's QuickCheck'in bir bağlantı noktasıdır. Fonksiyonların veya yöntemlerin karşılaması gereken özellikler biçiminde programın bir spesifikasyonunu sağlamanıza ve özelliklerin çok sayıda rastgele oluşturulmuş durumlarda sahip olduğu FsCheck testlerine olanak tanır.

FsCheck CodePlex Sayfası

FsCheck Yazar Sayfası


Evet, FsCheck'in NUnit vb. Gibi geleneksel birim test çerçevelerinden çok daha fazlasını sunduğunu düşünüyorum.
Robert

11

Dglaubman'ın önerdiği gibi NUnit'i kullanabilirsiniz. xUnit.net ayrıca bunun için destek sağlar ve TestDriven.net ile iyi çalışır . Kod, NUnit testlerine benzer, ancak testi kapsayıcı bir türle sarmalama gerekliliği yoktur.

#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) 

1.9.1'den itibaren Xunit'in yeni aşırı yüklemeleri F # ile hasara neden oluyor gibi görünüyor.
Rick Minerich

@RickMinerich Koduma da aynı şeyi yaşadım. Doğru aşırı yüklemenin seçilebilmesi için açık tür ek açıklamaları ekledim. Ancak bu yok maalesef Kodunuza fazla gürültü ekleyin.
Erik Schierboom

11

Bence bu, benim de çok merak ettiğim çok ilginç bir soru. Şimdiye kadarki düşüncelerim sadece düşünceler, bu yüzden onları oldukları gibi alın.

Otomatik bir test paketinin güvenlik ağının bırakılamayacak kadar değerli olduğunu düşünüyorum, ancak bu etkileşimli konsol ne kadar çekici olsa da, bu yüzden her zaman yaptığım gibi birim testleri yazmaya devam etmeyi planlıyorum.

.NET'in temel güçlü yönlerinden biri, diller arası yetenekleridir. Yakında F # üretim kodu yazacağımı biliyorum, ancak planım C # ile birim testleri yazmak ve benim için yeni bir dilin ne olduğunu anlamamı kolaylaştırmak. Bu şekilde, F # ile yazdıklarımın C # (ve diğer .NET dilleri) ile uyumlu olup olmayacağını da test edebilirim.

Bu yaklaşımla, F # kodumun yalnızca dahili olarak kullanabileceğim, ancak genel API'mın bir parçası olarak ifşa edemeyeceğim bazı özelliklerinin olduğunu anlıyorum, ancak bunu bugün kabul ettiğim gibi, bazı şeylerin olduğunu kabul ediyorum. C #, uintCLS uyumlu olmayanları ifade etmeme (beğenmeme ) izin veriyor ve bu yüzden onları kullanmaktan kaçınıyorum.


2
Planın nasıl gidiyor? F # kodunu c # kodu ile test etmek kolay mıydı? F # öğrenmeye başladım ve planım projemin bir bölümünü f # dilinde yazmak ve aynı fikrim var: c # için f # için de birim testleri yazmak.
Peter Porfy

@ Herhangi bir güncelleme var mı? Ayrıca TDD'yi F # ile kullanarak akışa girmekte zorlanıyorum.
Scott Nimrod

1
@ScottNimrod Birkaç güncelleme: Pluralsight kurslarımdan dördü F # ile test veya TDD ile ilgili. Ayrıca Lanyrd profilimde birçok ücretsiz konferans konuşması kaydı bulacaksınız . Son olarak, blogum var .
Mark Seemann

3
@ScottNimrod Mark'ın PS kurslarının tamamını yeterince görmek için zaman ayırmanızı ve / veya para ödemenizi tavsiye edemem - hepsini kafanızda maksimum verimlilikle bir araya getirecektir. Özel ihtiyaçlarınız için geçerli olsa da olmasa da, "F # 'da İşlevsel Mimari" ayrıca birçok noktayı birbirine bağlar ve güçlü bir şekilde dikkate alınmalıdır.
Ruben Bartelink

7

FSUnit'e bir göz atabilirsiniz - henüz kullanmamış olsam da denemeye değer olabilir. F # 'da örneğin (yerel) NUnit kullanmaktan kesinlikle daha iyidir.


1
ShdNx, neden NUnit'e karşı öneriyorsunuz? Don Syme'nin F # kitabı test için NUnit'i gösterir ve C #'da NUnit kullanmaya oldukça benzer görünür. FSUnit DSL harika görünüyor, ancak NUnit'e aşina olan kişiler için (Mathias "yıllardır TDD kullanıyor"), NUnit'i F # ile kullanmak C # veya VB'den daha sorunlu mu?
itowlson

İkinci itowlson yorumu ve sorusu. Kesinlikle F #'daki NUnit oldukça tuhaf görünüyor, ancak bunun yanında, başka bir şey kullanmayı iyi bir fikir haline getiren belirli sorunların farkında mısınız?
Mathias

1
"Oldukça tuhaf görünmenin" genellikle daha iyi bir şey bulmak için zorlayıcı bir sebep olduğunu söyleyebilirim. Garip görünmek, okunması zor, okunması zor, hatalar demektir. ("Garip görünmenin" "yeni ve / veya yabancı görünmekten" tamamen farklı olduğunu varsayıyorum - tanıdık olmayanlar aşina olacak, tuhaflık tuhaf kalacaktır.)
James Moore

1
Dürüst olmak gerekirse (cevabımda bahsettiğim gibi), henüz FSUnit kullanmadım, ancak NUnit'i F # ile kullanmanın çok acı verici olduğunu okudum. Öyle değilse özür dilerim.
ShdNx

4
Açık olmak gerekirse, FsUnit kullanıyorsanız TestFixtures ve Test üyeleriniz olacak. Sahip olmayacağınız şey, standart Assert.X çağrılarıdır. FsUnit, size NUnit'in bu bölümü etrafında, onu F # dilinde daha çok evde yapmanızı sağlayan bir sarmalayıcı sağlar.
Ray Vernagus

1

Partiye biraz geç kalmamıza rağmen Mathias'ı F #'a davet ediyorum (hiç olmamasından daha iyi;) ve birim test kitaplığım Expecto'yu beğenebileceğinizi söyleyin.

Expecto'nun beğenebileceğiniz bazı özellikleri vardır:

  • F # sözdizimi boyunca, değerler olarak test eder; testleri oluşturmak için düz F # yazın
  • İddialar için yerleşik Expect modülünü veya Unquote gibi harici bir kitaplığı kullanın
  • Varsayılan olarak paralel testler
  • Hopac kodunuzu veya Async kodunuzu test edin; Expecto baştan sona eşzamansızdır
  • Logary Facade aracılığıyla takılabilir günlük kaydı ve ölçümler; derleme sistemleri için adaptörleri kolayca yazın veya testlerinizin yürütme sürelerinin InfluxDB + Grafana panosunu oluşturmak için zamanlama mekanizmasını kullanın
  • BenchmarkDotNet için yerleşik destek
  • FsCheck için destek oluşturun; oluşturulan / rastgele verilerle testler oluşturmayı veya nesnenizin / aktörün durum uzayının değişmez modellerini oluşturmayı kolaylaştırır

-

open Expecto

let tests =
  test "A simple test" {
    let subject = "Hello World"
    Expect.equal subject "Hello World" "The strings should equal"
  }

[<EntryPoint>]
let main args =
  runTestsWithArgs defaultConfig args tests

https://github.com/haf/expecto/

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.