-
-
Notifications
You must be signed in to change notification settings - Fork 704
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
Named unittests: Introducing std.experimental.testing #3207
Conversation
|
The most glaring obvious thing to me is definately comments. At Least have some Returns/Params for the public API. |
| __gshared WriterThread _instance; | ||
| } | ||
|
|
||
| private void threadWriter() |
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.
Nice, we just have a PR for asynclogger.
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 hadn't even connected those this to asynclogger! I wrote this code more than a year ago, it's been the same for most of its life (I think, git might prove me wrong).
|
Documentation preview. |
|
@rikkimax Could you give an example of where the comments aren't enough? I thought I'd added enough all over but clearly I was wrong. @MartinNowak What would I have to do to update the documentation on that link? |
| string escCode(in string code) @safe pure const | ||
| { | ||
| return _useEscCodes ? _escCodes[code] : ""; | ||
| } |
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.
these four methods should be static.
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.
They can't, _useEscCodes is an instance variable.
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.
commented to the wrong line! "yellow" and friends should be static as there is no way for the user AFAIK to change _escCodes
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.
You're right, and I changed _escCodes to static immutable. However, yellow and friends all call escCode which in turn depends on _useEscCodes which is an instance variable.
|
s/if(/if (/g |
| { | ||
| import std.array; | ||
| super(msgLines.map!(a => getOutputPrefix(file, line) ~ a).join("\n")); | ||
| } |
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.
Exceptions usually allow chaining. have a look at the exceptions in std.csv
file and line usually have default values of FILE and LINE
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'm not sure what you mean by the chaining here. I added defaults for file and line.
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.
usually the last (default) arg to a exception is Exception. aka Exception chaining!
|
Main problem here is still requirement for explicit registration of modules. This does not feel robust enough to be proudly presented by Phobos. At the very least it needs to provide module for stub |
| * IO related functions | ||
| */ | ||
|
|
||
| module std.experimental.testing.io; |
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 think all "verbose" I/O should be done via std.experimental.logger.
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.
Yes, possibly. I wrote all of this long before std.experimental.logger existed, of course. I'm going to have to look into it.
It might just be that I need another logger backend for multithreaded applications first, though.
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 default logger is already thread-safe
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.
So I finally took a look at std.experimental.logger. With @Dicebot's comment, I feel like the only thing to change is to remove writelnUt (I realised later it's pretty much useless, it has the same effect as using plain old writeln in a unit test). Or I could remove everything except the ANSI colours from the io.d file and completely rework the current IO to use std.experimental.logger. The only verbose IO supported by this library was when the -d option was used, and all that did was stop turning off stdio and stderr.
|
Is there a reason why verbose |
|
I was playing about with |
|
Yes, I have a very bad opinion of wordings like |
|
I guess that's a matter of taste. I prefer should to expect, and expect to test. I'd prefer it even more if all of these worked: For some reason dmd is perfectly fine with an equality statement by itself but complains when it's But then the other operators would have to be passed in as compile-time strings, so no consistency. In the end I kept things as they were for this PR. |
|
|
|
Why would |
|
@Dicebot On the explicit registration, what would you propose beyond the |
|
All "good" solutions I can imagine require fixing language at least a bit :) For now I'd propose to provide separate module |
As I have already mentioned, it is a very clear indicator that library author values "pretty" test definitions that increase visual complexity at no added value (which, in my opinion, is fundamental flaw of almost all modern test frameworks). I like D tests because they are very KISS and using both operator overloading and "spoken" language (I don't care what function "should" do, I simply test what it does!) smells as not KISS at all. Every abstraction needs to be justified with "what does that actually give you in return?".
Yes, something very similar. Otherwise everyone will write the same thing of their own ;) |
I guess that's acceptable as a start. But we need a proper tool for this sooner rather than later.
So I need to run Then The user should not need to know or care there's an intermediate file. In that case, you can generate a temporary file and skip the |
|
I still think such a tool belongs in |
|
Having thought a bit about
I'm aware my proposal isn't ideal - but that's what's possible given the state of compile-time reflection in D now. @Dicebot, @jacob-carlborg : thoughts? |
|
I have given this some though as well. In an ideal world the build tool would handle this. Alternative A:
The problems with this are:
It's possible to find the test methods at runtime by inspecting the symbol table (yes I know, it's a hack). Alternative B:
The problem with this is:
Alternative C:
The problem with this are:
I guess Alternative C is what you have in mind. I'm not sure how dtest works now but you could always generate a file with all tests (regardless which ones should be executed) then at runtime select which test should be run. This way you could cache the intermediate file which only needs to be updated when tests are added or removed. |
|
Libraries and compile-time reflection don't mix, so it's alternative C except that a hidden file isn't as useful as one that gets generated automatically by the build system / on demand when the list of modules to be compiled changes. |
6a41bad
to
f852a1b
Compare
Apart from those issues I warmly accept this module! |
|
I agree it'd be better that the compiler assert do this work. But it's easier to do it in a library. I don't see why unit tests need to be I added a link to the docs. |
|
The most appearant use would be to make sure that a specific Phobos algorithm/range doesn't accidentally use the GC nor throw exceptions for a specific set of element types. This is currently a hot topic because many Phobos algorithms accidentally make unnecessary use of the GC. We can't tag the template ranges/functions as What if I fix DMD to make asserts have better diagonistics? :) What format do you want for a failing assert? Do you want to print the values of |
|
@nordlow Knock yourself out ;) I've looked into changing assert in dmd myself; if it were easy I'd've already done it |
|
I don't know what Walter would accept at this point, but after |
|
What's costing memory? Extra AST-nodes in DMD? |
|
Read the comments in the bug report I listed. That's all the information that I have on the details of why it would or wouldn't be a good idea. But according to Don, you have to copy the parameters, which can be expensive, and Walter was against the increased memory requirements. If you can come up with something that makes assertion messages show more useful information and which gets past Walter and the rest of the compiler dev team, then great, but there was a previous attempt to make assert print out the values of of the variables involved - e.g. printing out the values of lhs and rhs in assert(lhs == rhs) - and it was rejected by Walter. Walter thought that it should be done with library functions instead. I don't know what Walter's stance on it would be at this point. |
|
What about adding a specific compiler flag (argument), say Typically added/modified by the developer by changing the flags to calls to rdmd/dub/scons etc upon failure with If DMD is called with assert(lhs == rhs)with assertBinOp(A_FILE, A_LINE, A_COLUMN, "==")(lhs == rhs, lhs, rhs)where assertBinOp(string file, uint line, uint column, string op)(E, L, R)(lazy E expression, lazy L lhs, lazy R rhs)and similarly for unary expressions. The default implementation of This specific behaviour could be extendable by adding (typically templated) overloads of Then we could get the extendability we want in testing-frameworks such as this without adding a new Further with this solution we could add cool diagnostics behaviour in For example a failing assert([1,2,3] == [1,2,4]);could fancy-print or for aggregates a failing struct A { int x, y; }
auto a = A(1,2);
auto b = A(1,3);
assert(a == b);could fancy-print Thereby giving D yet another feature, I've not seen in any other language :) If needed I'd be more than happy to help out implementing this solution in dmd/druntime/phobos. I'm guessing that parts of the solution list at https://issues.dlang.org/show_bug.cgi?id=5547#c3 can be reused, right? @WalterBright @andralex What do you think? |
|
@nordlow sounds interesting - please write a DIP as I mentioned in the forum |
| * args = Arguments passed to main. | ||
| * Returns: An integer suitable for the program's return code. | ||
| */ | ||
| int runTests(MODULES...)(string[] args) |
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.
Why not Modules instead of uppercase?
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.
All caps is in violation of the official style guide, so it really should be changed. And unless MODULES is a type (and it doesn't look like it is), it should be camelCased, not PascalCased, so it would then be modules, not Modules.
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 agree.
|
This was rejected in the voting thread. Time to close? |
|
I wanted to resubmit a simpler proposal, but I guess it makes sense to close this one as it is now. |
Docs here