In your example modification, the caller function wouldn't be able to
actually access any of those internal closures, and the callee wouldn't be
able to define more than one test() method.
Instead, you could do something like the following, although I don't think
it's necessarily any better than the macro version, it is perhaps a bit
more flexible since you could reuse and curry function more easily, whereas
the macros mostly force you to write out the explicit syntax. (note that
()->begin;end and function();end are just different ways of writing exactly
equivalent expressions)
testcase() do T
T.casename = "Mytest Tests"
#Some code
x = 0
#Function to be called before each test (optional)
T.setUp = function()
x += 1
end
#Function to be called after each test (optional)
T.tearDown = function()
x=0
end
push!(T.tests, function()
testname("A Simple Test") #Name of test (optional)
@assertEqual(x,1)
end)
#more tests or code...
end # end of test case
On Sat, Nov 1, 2014 at 1:24 PM, Jason Merrill <[email protected]> wrote:
> On Saturday, November 1, 2014 10:01:48 AM UTC-7, Jason Merrill wrote:
>>
>>
>> On Thursday, October 30, 2014 8:08:23 PM UTC-4, Sal Mangano wrote:
>>>>>>
>>>>>> I wanted a unittest framework that worked more like unittest in
>>>>>> python (or xUnit in in other languages) so I wrote [email protected]:
>>>>>> smangano/JLTest.git. If you find it useful great. I am still new to
>>>>>> Julia so if you find anything showing poor taste I am happy to get
>>>>>> critique
>>>>>> and/or suggestions for improvement. I'll try to add better docs but I
>>>>>> think
>>>>>> it is pretty self explanatory if you look at test/runtests.jl
>>>>>>
>>>>>>
>>>>>>
>> Re: macros, in places where you have macros that should take a function,
>> or that will usually be called with a begin ... end block, you can often
>> replace them with a plain old function and simplify the implementation.
>> Julia's `do` syntax makes this especially easy. Same goes for macros that
>> take a string and don't use it to generate code.
>>
>> Borrowing the example from the readme:
>>
>> using JLTest
>>
>> @testcase begin
>> @casename "Mytest Tests"
>>
>> #Some code
>> x = 0
>>
>> #Function to be called before each test (optional)
>> @setUp () -> (x+=1)
>>
>> #Function to be called after each test (optional)
>> @tearDown () -> (x=0)
>>
>> @test begin
>> @testname "A Simple Test" #Name of test (optional)
>> @assertEqual(x,1)
>> end
>>
>> #more tests or code...
>>
>> end # end of test case
>>
>>
>> Could become
>>
>> using JLTest
>>
>> testcase() do
>> casename("Mytest Tests")
>>
>> #Some code
>> x = 0
>>
>> #Function to be called before each test (optional)
>> setUp() do
>> x += 1
>> end
>>
>> #Function to be called after each test (optional)
>> tearDown() do
>> x=0
>> end
>>
>> test() do
>> testname("A Simple Test") #Name of test (optional)
>> @assertEqual(x,1)
>> end
>>
>> #more tests or code...
>>
>> end # end of test case
>>
>>
>> So concretely, I'm suggesting testcase, casename, setup, teardown, test,
>> and testname could (should?) maybe all be functions instead of macros.
>>
>> The assertions are probably best left as macros, since they actually get
>> something out of delayed evaluation (i.e. being able to print the original
>> expresions when they fail).
>>
>
> I just took a look at the actual implementation, and it looks like part of
> the reason for all the macros is to have a kind of dynamic scoping--i.e.
> inside a testcase block there is an implicit current TestCase instance. I'm
> curious if others have suggestions about how to manage dynamic scoping like
> this (am I even using that term correctly?). It seems like something that
> comes up in a number of places, and I'm not sure if there's a consensus on
> it yet. One place I'm thinking of is in some of the plotting libraries,
> where you want to build up a plot incrementally, so it's desirable to have
> an idea of "the current plot".
>