
Hi, I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing. I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code? What framework lends itself better for writing tests before the actual production code? Can you point out to some resources regarding this? Oh, and a small off-topic question? Is it considered a good practice to use implicit imports in Haskell? I'm trying to learn from existing packages, but all those "import all" statements drive me crazy. Thanks, -- IonuČ› G. Stan | http://igstan.ro

On Tuesday 25 May 2010 13:36:01, Ionut G. Stan wrote:
Hi,
I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code?
And ghci or hugs are the most used tools for testing, be the code pure or impure.
What framework lends itself better for writing tests before the actual production code? Can you point out to some resources regarding this?
You can write the QuickCheck properties that your functions should satisfy before implementing the functions. However, when you've determined the specs, it's rather unimportant whether you write the properties first or the functions, IMO.
Oh, and a small off-topic question? Is it considered a good practice to use implicit imports in Haskell?
Generally, no. It's considered good practice to use explicit import (and export, of course) lists. But as lazy programmers, we can't always resist the temptation to skip some not strictly necessary work. The implicit import of the entire Prelude is a special case, modules from the same package are edge cases, but otherwise it's a code smell.
I'm trying to learn from existing packages, but all those "import all" statements drive me crazy.
Thanks,

On 5/25/10 2:50 PM, Daniel Fischer wrote:
On Tuesday 25 May 2010 13:36:01, Ionut G. Stan wrote:
Hi,
I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code?
And ghci or hugs are the most used tools for testing, be the code pure or impure.
Well, probably. I'm looking for an automated solution though. I want to be able to rerun the tests on every commit or version release.
What framework lends itself better for writing tests before the actual production code? Can you point out to some resources regarding this?
You can write the QuickCheck properties that your functions should satisfy before implementing the functions. However, when you've determined the specs, it's rather unimportant whether you write the properties first or the functions, IMO.
It may be true. I've got accustomed though to write code in iterative steps, where I first think about the smallest feature that I want to implement, then write the test, then again feature -> test -> code/refactor. I will certainly have to adapt my work flow within the Haskell way of doing things, until then though I'll start from what I know has produced good results for me and change it along the way.
Oh, and a small off-topic question? Is it considered a good practice to use implicit imports in Haskell?
Generally, no. It's considered good practice to use explicit import (and export, of course) lists. But as lazy programmers, we can't always resist the temptation to skip some not strictly necessary work. The implicit import of the entire Prelude is a special case, modules from the same package are edge cases, but otherwise it's a code smell.
I thought so. Good to know.
I'm trying to learn from existing packages, but all those "import all" statements drive me crazy.
Thanks,
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Thanks, -- IonuČ› G. Stan | http://igstan.ro

On Tuesday 25 May 2010 14:36:46, Ionut G. Stan wrote:
On 5/25/10 2:50 PM, Daniel Fischer wrote:
On Tuesday 25 May 2010 13:36:01, Ionut G. Stan wrote:
Hi,
I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code?
And ghci or hugs are the most used tools for testing, be the code pure or impure.
Well, probably. I'm looking for an automated solution though. I want to be able to rerun the tests on every commit or version release.
Good practice. You can configure darcs to run the tests on every record (or version-tag or whatever). The testing in ghci/hugs is primarily done while writing the code, after that QuickCheck takes over.
What framework lends itself better for writing tests before the actual production code? Can you point out to some resources regarding this?
You can write the QuickCheck properties that your functions should satisfy before implementing the functions. However, when you've determined the specs, it's rather unimportant whether you write the properties first or the functions, IMO.
It may be true. I've got accustomed though to write code in iterative steps, where I first think about the smallest feature that I want to implement, then write the test, then again feature -> test -> code/refactor.
I will certainly have to adapt my work flow within the Haskell way of doing things, until then though I'll start from what I know has produced good results for me and change it along the way.
You will have to adapt your way of thinking about your tasks to Haskell (discover new fun ways of doing things :D), but I see no reason why you should stop writing the tests first. What I meant is, once you know what the function should do, it's not important whether you write the Quickcheck property before the function or the other way round - you can't run the tests before both are written anyway :) Of course, if you write the tests first, you don't risk omitting them.

I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
TDD can be deciphered as Type Driven Design, and right now not so many languages would allow you to experience this. Take a look at this previous post here: http://www.haskell.org/pipermail/haskell-cafe/2010-May/077154.html

On 25 May 2010 13:36, Ionut G. Stan
I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code?
What framework lends itself better for writing tests before the actual production code? Can you point out to some resources regarding this?
Real World Haskell has a chapter dedicated to writing Tests for your code using QuickCheck[1]. The writers of this book work in industries where well tested programs are essential. Personally I suppose I follow a methodology of type driven development followed by tests. I wrote a simple Emacs library to make testing QuickCheck properties easier[2]. It's convenient because it lets you check a function when your cursor is at the definition, or test all properties in the current file. It picks up properties by symbols named foo_prop, where foo is the function that the foo_prop property is written for. Maybe this workflow suites your needs.
Oh, and a small off-topic question? Is it considered a good practice to use implicit imports in Haskell? I'm trying to learn from existing packages, but all those "import all" statements drive me crazy.
I would follow tibbe's Haskell style guide[3] because it is strict and reasonable. To quote it on this topic: "Always use explicit import lists or qualified imports for standard and third party libraries. This makes the code more robust against changes in these libraries. Exception: The Prelude." [1]: http://book.realworldhaskell.org/read/testing-and-quality-assurance.html [2]: http://www.emacswiki.org/emacs-en/QuickCheckHaskell [3]: http://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md

On 25 May 2010 13:25, Christopher Done
I would follow tibbe's Haskell style guide[3] because it is strict and reasonable. To quote it on this topic:
"Always use explicit import lists or qualified imports for standard and third party libraries. This makes the code more robust against changes in these libraries. Exception: The Prelude."
[3]: http://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md
The possible advantage in robustness is pretty small - if the imported library adds and exports a new definition using a name you were already using then you'll get a name conflict. The GHC style guide has better[*] reasons for avoiding them: http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle [*] "Better" - as in it conforms to my prejudice.... Best wishes Stephen

On Tue, May 25, 2010 at 12:36 PM, Ionut G. Stan
Oh, and a small off-topic question? Is it considered a good practice to use implicit imports in Haskell? I'm trying to learn from existing packages, but all those "import all" statements drive me crazy.
It's pretty common but I don't like it. Whenever I have to debug someone else's code usually the first thing I'll do is make all the import lists explicit so I can work out where a troublesome function is coming from, and that's a bit of a waste of time. In some cases though it can get a little silly. Here is an import statement from one of my projects: import Language.Haskell.Exts ( Alt (Alt), Binds (BDecls), Decl (PatBind, FunBind, InfixDecl), Exp (App, Case, Con, Do, If, InfixApp, Lambda, LeftSection, Let, List, Lit, Paren, RightSection, Tuple, Var, XPcdata), GuardedAlt (GuardedAlt), GuardedAlts (UnGuardedAlt, GuardedAlts), Literal (Char, Frac, Int, String), Match (Match), Op (ConOp, VarOp), Pat (PApp, PInfixApp, PList, PLit, PParen, PTuple, PVar, PWildCard), Name (Ident, Symbol), QName (Special, UnQual), QOp (QConOp, QVarOp), Rhs (UnGuardedRhs), SpecialCon (Cons), SrcLoc (), -- (SrcLoc), Stmt (Generator, LetStmt, Qualifier), preludeFixities, prettyPrint ) ...there comes a certain point where one can probably leave the biggest import implicit, on the basis that "if it's from nowhere else, it's probably there".

On 25/05/10 12:36, Ionut G. Stan wrote:
Hi,
I'm doing TDD in pretty much all of the languages that I know, and I want to introduce it early in my Haskell learning process. I wonder though, if there's some established process regarding TDD, not unit testing.
I've heard of QuickCheck and HUnit, but I've also read that QuickCheck is used mostly for testing pure code, while HUnit for impure code?
I tend to use HUnit more than QuickCheck (even for pure code), but that may be a reflection of the projects I've worked on. Reasons why I have used HUnit: - Writing an Arbitrary instance for a data type wasn't worth the effort. When writing a nanopass compiler, it seemed like too much effort to write an Arbitrary instance to produce a valid fragment of AST for that particular pass (given that each pass would probably need a different instance). Problems with the instance include: * If I allowed every instance to generate the full variety of AST elements, the chances of generating an AST fragment that tested the pass in question would be vanishingly small, which would require customising the instance (or adding generation conditions) in fiddly ways for each pass to make sure I got good coverage. * For most passes, the AST must obey many pre-conditions, such as all variables being declared before use, all expressions type-checking, passing various safety/sanity checks and so on. All these (and different sets of them) would need to be considered for each Arbitrary instance, which adds a lot of effort to the instance generation, when I can easily craft a few targeted pieces of input myself. - With some functions I can provide an exhaustive check of all inputs, for which QuickCheck is ill-suited. This would suit SmallCheck and LazySmallCheck, but often it's just easier to write something like: assertTrue $ and [checkResult x (f x) | x <- allInputs] than to use the other frameworks. - For QuickCheck 1, testing of things like IO actions was very difficult (I think unsafePerformIO was needed?) but QuickCheck 2 is much better in that regard once you've gone the hang of it. More generally, I often think it is less effort to test the corner/edge cases carefully with HUnit than it is to express the properties of the function (and the properties are almost always noticeably longer than the function being tested) and construct an Arbitrary instance that produces valid input. Perhaps I just haven't worked on the right projects for QuickCheck or haven't got into the property-based testing mindset, though. Thanks, Neil.
participants (7)
-
Ben Millwood
-
Christopher Done
-
Daniel Fischer
-
Ionut G. Stan
-
Neil Brown
-
Serguey Zefirov
-
Stephen Tetley