From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.0 required=5.0 tests=none autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id 418E7BBC1 for ; Fri, 14 Mar 2008 01:53:44 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnQDAIdp2UdIDvb1ZGdsb2JhbACQaxgEBAkKGZIDhxE X-IronPort-AV: E=Sophos;i="4.25,497,1199660400"; d="scan'208";a="10248880" Received: from discorde.inria.fr ([192.93.2.38]) by mail3-smtp-sop.national.inria.fr with ESMTP; 14 Mar 2008 01:53:44 +0100 Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id m2E0rhTo012645 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Fri, 14 Mar 2008 01:53:43 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnQDAIdp2UdIDvb1ZGdsb2JhbACQaxgEBAkKGZIDhxE X-IronPort-AV: E=Sophos;i="4.25,497,1199660400"; d="scan'208";a="10248879" Received: from ag-out-0708.google.com ([72.14.246.245]) by mail3-smtp-sop.national.inria.fr with ESMTP; 14 Mar 2008 01:53:41 +0100 Received: by ag-out-0708.google.com with SMTP id 9so5916065agd.9 for ; Thu, 13 Mar 2008 17:53:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; bh=5LaJSayXkqHI/PPFCg7LCwkmHP+PUAVzFCvASLOB0dU=; b=tZuubKgvjghW6M/osY+BpzUdF+7CDhcEXkWQEFjt51EDp/j3KxQVfLIF0F6NsU5cMdYcn1SI7o+2Qsly48uOyOtlvnvpkBNX24MwXhEaCXDhtz6EIvkzIO6yiV+BdwRwbBYD5qs7P6/4bFimKQh9KYMjwlCwt5nxAi1//gbWpS8= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:to:subject:cc:in-reply-to:mime-version:content-type:content-transfer-encoding:content-disposition:references; b=ezsyMJz6lQ/OCmQitwm2fTSQCbpUvClKpY6CtEeus+V4uhqtGJUM//772hHhCnxdMWZ5syQ/NZMPc7PCzAYHme8Jh/xmobbZfzM/k1PfXvF6crD1Yb8Zsokqrj0maWtRxvedCe7DRK9bNVb1s1cr8d7sr20WxxLHi+TPKLKmhkk= Received: by 10.101.66.14 with SMTP id t14mr21109190ank.114.1205456017685; Thu, 13 Mar 2008 17:53:37 -0700 (PDT) Received: by 10.100.136.16 with HTTP; Thu, 13 Mar 2008 17:53:37 -0700 (PDT) Message-ID: Date: Fri, 14 Mar 2008 08:53:37 +0800 From: "Ludovic Coquelle" To: "Andrew Gacek" Subject: Re: [Caml-list] invoke function from its name as string Cc: Andrej.Bauer@andrej.com, Caml In-Reply-To: MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-Disposition: inline References: <47D8CE92.2020009@fmf.uni-lj.si> <47D9594C.7080505@fmf.uni-lj.si> X-Miltered: at discorde with ID 47D9CC97.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; andrej:01 advices:01 andrej:01 'make:01 ocaml:01 bool:01 iter:01 failwith:01 ocaml:01 beginner's:01 bug:01 blog:98 blog:98 invoke:01 beginners:01 I like the "global test registry" of Andrej and will give it a try (adapted to OUnit). Thanks for all the advices! On Fri, Mar 14, 2008 at 1:03 AM, Andrew Gacek wrote: > Andrej's solution is interesting since it lets you interleave the > regular code with the test code. For my own code, I keep all tests > isolated to separate files and in each file I maintain the tests as a > list of anonymous functions. As a made-up example I might have > > let list_tests = > "List" >::: [ > "Empty list has length zero" >:: > (fun () -> > assert_equal 0 (List.length [])) ; > > "Empty list appended to empty list is empty list" >:: > (fun () -> > assert_equal [] ([] @ [])) ; > > ... > > ] > > This structure makes it very easy to add new tests and does not > require me to come up with > convoluted_test_function_names_with_undersctores. The downside is that > tests end up being indented so much. > > -Andrew > > On Thu, Mar 13, 2008 at 11:41 AM, Andrej Bauer > > wrote: > > > > Ludovic Coquelle wrote: > > > Thanks for this answer. > > > Problem I'm trying to solve is the following: > > > > > > I use 'make_suite' which is a program that do regex matching on source > > > code to extract a list of function that looks like OUnit tests; from > > > this list, it write an ocaml source code file which is a test case > > > that call all the previous functions found. > > > (see: http://skydeck.com/blog/programming/unit-test-in-ocaml-with-ounit/) > > > > I looked at the blog post. The idea is to interleave the source code > > with special test functions and extract those automatically. You have > > chosen to do this by searching the source code with regular expressions, > > looking for functions with a certain name. If I may be honest and will > > all due respect: this is a really horrible idea. It is fragile, > > sensitive to mistakes, you have no guarantee that all the test functions > > were actually found (say what if someone mispells the name of one of > > them slightly), and so on. It is just really bad. > > > > How about the following solution, in which I naively assume that test > > functions are supposed to return bool, but this is easily fixed. Define > > a module "Test" somewhat like this: > > > > ---test.ml---- > > (** The list of tests registered by the source code. *) > > let tests = ref [] > > > > (** Register a function as a test. *) > > let register name test = > > tests := (name, test) :: !tests > > > > (** Run all tests, maybe we can combine this with OUnit? *) > > let run_tests () = > > List.iter > > (fun (name,test) -> > > if not (test ()) then failwith ("FAILED: " ^ name)) > > !tests > > ------------- > > > > In your source code, whenever you want to have a test you just write: > > > > Test.register "some_name" (fun () -> > > (*test code here*) > > *) > > > > This is essentially the same overhead as what you have in your current > > solution, except that it is robust, ocaml will check that it is ok, and > > you do not have to come up with names of test functions of the form > > test_... all the time. The names of tests are strings, they can be more > > descriptive. > > > > To run your program, you do not do anything special. There will be a > > small initialization cost when the test functions are collected in the list. > > > > Tu run the tests, you link your source code with something like > > > > ---runtest.ml--- > > > > Test.run_tests () > > > > --------------- > > > > You can easily extend this idea to using OUnit inside test.ml or do > > whatever you like. The important thing is that you do not search the > > source code in a naive and fragile way that requires to programmer to > > follow arbitrary naming conventions. > > > > Best regards, > > > > Andrej > > > > > > > > _______________________________________________ > > Caml-list mailing list. Subscription management: > > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > > Archives: http://caml.inria.fr > > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > > Bug reports: http://caml.inria.fr/bin/caml-bugs > > >