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 mail1-relais-roc.national.inria.fr (mail1-relais-roc.national.inria.fr [192.134.164.82]) by yquem.inria.fr (Postfix) with ESMTP id C2545BBC1 for ; Thu, 13 Mar 2008 18:03:40 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ah0DAOb62EfAXQImh2dsb2JhbACQcwEBAQgKKZA4hn4 X-IronPort-AV: E=Sophos;i="4.25,495,1199660400"; d="scan'208";a="9406546" Received: from discorde.inria.fr ([192.93.2.38]) by mail1-smtp-roc.national.inria.fr with ESMTP; 13 Mar 2008 18:03:40 +0100 Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by discorde.inria.fr (8.13.6/8.13.6) with ESMTP id m2DH3LBA029985 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=OK) for ; Thu, 13 Mar 2008 18:03:40 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AoICAOb62EdIDvbxZGdsb2JhbACQZhgEBAkKGZA3hn4 X-IronPort-AV: E=Sophos;i="4.25,495,1199660400"; d="scan'208";a="8359128" Received: from ag-out-0708.google.com ([72.14.246.241]) by mail2-smtp-roc.national.inria.fr with ESMTP; 13 Mar 2008 18:03:39 +0100 Received: by ag-out-0708.google.com with SMTP id 9so5611843agd.9 for ; Thu, 13 Mar 2008 10:03: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=fE22DiRzIYfnP7FuSZ/1uPEmcbwkSf+l+xi2S/T90nU=; b=XHFKS4JYbbJBnyOt60qWMbOQwyqZreH5ZyU+o8bHJaXKdjnijpBEfO5JIkP/Y8h963fNJEZwKmDxEjjGmxDXAGz4kNMlkyZxTGKJ42CT3S8xjkUwn1vZlG+/S6cvpP375jUMpxnc+gmV3skU6BUAtCzxHjh00dEEqdTPUskQQWI= 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=T8DPyGnYDfuI6Ps02Gw9tfYmu9FpwccVQ5PwKa9I+/bFMGil88v9pS0J4ZkqAGECzBcyrcgw7EjQzNqkOzgZJCPHK1f5CYTgkFexmDdZvV5wHOzznHg58rEsi4Om1vv8s/8cGIs//685OfRu7g6lhHG/yQjJNsDumt9L+4cLLJU= Received: by 10.150.196.5 with SMTP id t5mr5567057ybf.40.1205427817308; Thu, 13 Mar 2008 10:03:37 -0700 (PDT) Received: by 10.150.220.4 with HTTP; Thu, 13 Mar 2008 10:03:37 -0700 (PDT) Message-ID: Date: Thu, 13 Mar 2008 12:03:37 -0500 From: "Andrew Gacek" To: Andrej.Bauer@andrej.com Subject: Re: [Caml-list] invoke function from its name as string Cc: "Ludovic Coquelle" , Caml In-Reply-To: <47D9594C.7080505@fmf.uni-lj.si> 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 47D95E59.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; andrej: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 wrote:01 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 >