-
Notifications
You must be signed in to change notification settings - Fork 25
Test Module #259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Test Module #259
Conversation
|
I highly suggest the following style of writing test suites: That way it will be much easier to introduce |
This would work, if suites were flat structures. But since we made them tree-like, allowing suites to contain other suites, this will not work. |
|
I still consider nested test suites to be a bloat. We dont have fixtures, so there really is not need to complicate this mechanism. Also what difference does make |
|
I prefer this solution because of its scalability. While current implementation doesn't really make use of these structures being nested, this module is rich in avenues for extension. So:
|
|
I also no see that I misunderstood your earlier comment. |
wojpok
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From the functional standpoint, the code is fine. I don't like some of the design decisions. I don't get the idea of global tests and recursive suites. There should be just regular suites and nothing more. Let's discuss this with rest of the team during the next meeting.
| , errorType : ErrorType | ||
| } | ||
|
|
||
| {# TODO : Add tags to tests and suites #} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't. Tags will handled using attributes as already agreed upon
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe we did. From what i remember we discussed what attributes should be, but at the time we didn't consider how this would change once there is a proper testing module in place, and we considered that there could be changes.
As to why i think this would be advantageous, firstly having it expressed inside language gives use much more flexibility, secondly it allows for having a far more fine-grained tags.
I can imagine having a test file with
let tags = ...
defined at the top, and being able to pass just this named parameter, instead of having to write it out every time.
However this seems to be another thing to be discussed at the meeting.
lib/Test.fram
Outdated
| , body : Unit ->[IO] List ErrorInfo | ||
| } | ||
|
|
||
| data rec TestSuiteInternal = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neither TestSuiteInternal nor TestSuite are public. User can't interact with them directly, hence why the redundancy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second one is abstr, as it should be usable outside the module.
TestSuiteInternal shouldn't be visible outside this module and so the handle is returned.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Abstr makes type visible outside module. User can't interact with this structure unless public function/method is provided, just like you already did. You can move all data from TestSuiteInternal to abstract TestSuite and user will have no idea that there are any additional data. The most delicate part of this structure are references that are in fact already shared. There is no immediate benefit to this structure.
lib/Test.fram
Outdated
| method printTestSuccess (TestCase { name, line, file }) = | ||
| printStr "[ \{ Color.setFgColor Color.Green | strFmt }OK"; | ||
| printStr "\{Color.resetAll | strFmt} ]"; | ||
| printStrLn " \{ name | strFmt} from \{ file | strFmt }:\{ line | strFmt }" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a need to include test definition location. It looks ugly honestly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it looks fine, i guess something else to vote on :D.
| ##} | ||
| data TestArbiter E = | ||
| { abort : {X} -> ErrorInfo ->[E] X | ||
| , fail : ErrorInfo ->[E] Unit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fail is confusing. It does not indicate that contrary to abort the test is resumed upon calling fail.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I couldn't find a better name for saying that if condition isn't met, the test is resumed but is considered failed.
Also in my opinion the type says it very well, fail always returns unit, contrary to abort which never returns.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough. Consider adding a comment that explains the difference. That will do for me
lib/Test.fram
Outdated
| let tests = ioMut.ref [] in | ||
| let suite' = TestSuiteInternal { name, file, line, tests, suites } in | ||
| suite.addSuite suite'; | ||
| TestSuite { suites, tests } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reference to recursive suites and test list is shared. Why are you using different 2 objects here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As answered above, this is the place where this is used.
Foxinio
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed most of the comments, all that's left is to conform this module to what we agree on in the meeting.
lib/Test.fram
Outdated
| , body : Unit ->[IO] List ErrorInfo | ||
| } | ||
|
|
||
| data rec TestSuiteInternal = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The second one is abstr, as it should be usable outside the module.
TestSuiteInternal shouldn't be visible outside this module and so the handle is returned.
lib/Test.fram
Outdated
| let tests = ioMut.ref [] in | ||
| let suite' = TestSuiteInternal { name, file, line, tests, suites } in | ||
| suite.addSuite suite'; | ||
| TestSuite { suites, tests } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As answered above, this is the place where this is used.
lib/Test.fram
Outdated
| method printTestSuccess (TestCase { name, line, file }) = | ||
| printStr "[ \{ Color.setFgColor Color.Green | strFmt }OK"; | ||
| printStr "\{Color.resetAll | strFmt} ]"; | ||
| printStrLn " \{ name | strFmt} from \{ file | strFmt }:\{ line | strFmt }" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To me it looks fine, i guess something else to vote on :D.
| , errorType : ErrorType | ||
| } | ||
|
|
||
| {# TODO : Add tags to tests and suites #} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe we did. From what i remember we discussed what attributes should be, but at the time we didn't consider how this would change once there is a proper testing module in place, and we considered that there could be changes.
As to why i think this would be advantageous, firstly having it expressed inside language gives use much more flexibility, secondly it allows for having a far more fine-grained tags.
I can imagine having a test file with
let tags = ...
defined at the top, and being able to pass just this named parameter, instead of having to write it out every time.
However this seems to be another thing to be discussed at the meeting.
lib/Test.fram
Outdated
| data rec TestSuiteInternal = | ||
| { name : String | ||
| , line : Int | ||
| , file : String | ||
| , suites : Ref IO (List TestSuiteInternal) | ||
| , tests : Ref IO (List TestCase) | ||
| } | ||
|
|
||
| abstr data TestSuite = | ||
| { suites : Ref IO (List TestSuiteInternal) | ||
| , tests : Ref IO (List TestCase) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is meant to be two part. One is the internal representation, the other is a public facing handle to access test module interface. Probably this could be reduced to one abstract type, and the semantics should be preserved. But i don't see any harm in having both, and separating them based on the use result's in much clearer code.
|
I have made up my mind. I am fine with this code as is. It would be nice to merge TestSuiteInternal and TestSuite to single structure, but I won't enforce that. Only issue at hand is lack of any mechanism to toggle test excecution. If you provide a suitable way of controlling it I will approve this PR |
|
I agree, it has to be done, and so I left a TODO comment. However I think it's best to merge it in this state and improve in a later PR, as this change would require a significant amount of code to be written. In my opinion, for now, we can live with all included tests being run. |
|
Not necessarily. What about a global flag that can be read using |
wojpok
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code is okay, all issues are resolved. I am not a fan of the command line output, but I don't really want to slow down the development. We need proper testing environment sooner than later
|
Work developed in this PR is to be continued in #289. |
In this PR I propose module to write structured tests.
(This implementation is inspired by one done by @wojpok, and included in #256)
Tests can be written like so:
Tests are run whenever file containing tests is included, in one passed to
dbl.This may seem undesirable, but will be addressed with introduction of attributes.