digitalmars.D - Static unittests?
- Bosak (11/11) Aug 05 2013 Are compile-time unittests possible in D? Maybe something like:
- Dicebot (2/13) Aug 05 2013 Not right now at the very least. Use case?
- monarch_dodra (19/21) Aug 05 2013 The use case is simply checking that your functions can be
- Dicebot (4/8) Aug 05 2013 Considering your, example, you can always do `static
- monarch_dodra (12/21) Aug 05 2013 Well, the "crucial" difference is that this tests a single
- Dicebot (8/9) Aug 05 2013 enum i;
- monarch_dodra (18/28) Aug 05 2013 You are working around the argument. The point is that some calls
- Dicebot (4/5) Aug 05 2013 Saying "test CTFE function that mutates its arguments" would have
- Artur Skawina (10/37) Aug 05 2013 static assert({
- Walter Bright (3/11) Aug 18 2013 I don't believe that is a valid use case because the code being tested i...
- monarch_dodra (33/45) Aug 19 2013 I'm not sure what that means. Isn't that the case of all unittest?
- Dicebot (4/7) Aug 05 2013 topic-starter has been asking about _language_ feature and my
- monarch_dodra (17/25) Aug 05 2013 Well, it's not about *proving* anything :/
- Dicebot (12/20) Aug 05 2013 Well, the problem is, D does have static unit-tests in a form of
- monarch_dodra (12/34) Aug 05 2013 Alright. I tend to try to give as much information as possible in
- Jacob Carlborg (6/17) Aug 05 2013 Not exactly as you describe but you can do unit tests for CTFE
- Andrej Mitrovic (10/14) Aug 05 2013 Nope.
- Jacob Carlborg (5/12) Aug 12 2013 It does work, at least when I added it:
- Andrej Mitrovic (4/6) Aug 12 2013 Hmm that does work! Looks like I must have hit some kind of bug
- Borislav Kosharov (8/8) Aug 17 2013 monarch_dodra got my point. So a static unittest is just like a
- Andrej Mitrovic (12/15) Aug 17 2013 Have you tried using the new getUnitTests trait in the git-head
- Borislav Kosharov (5/24) Aug 18 2013 Oh I really haven't tough about that. Maybe, I will try this new
- monarch_dodra (15/44) Aug 18 2013 Well, that assumes all your code is ctfe-able...
Are compile-time unittests possible in D? Maybe something like: static unittest { assert(2 == 1 + 1); } So that every assert in the unittest is translated to static assert. And no normal asserts to be allowed in static unittest? So the above code would be executed at compile time and translated to: unittest { static assert(2 == 1 + 1); }
Aug 05 2013
On Monday, 5 August 2013 at 12:25:36 UTC, Bosak wrote:Are compile-time unittests possible in D? Maybe something like: static unittest { assert(2 == 1 + 1); } So that every assert in the unittest is translated to static assert. And no normal asserts to be allowed in static unittest? So the above code would be executed at compile time and translated to: unittest { static assert(2 == 1 + 1); }Not right now at the very least. Use case?
Aug 05 2013
On Monday, 5 August 2013 at 14:02:06 UTC, Dicebot wrote:Use case?The use case is simply checking that your functions can be CTFE'd, and that they produce the correct result.Not right now at the very least.std.exception defines the package "assertCTFEable". It allows code such as: unittest { assertCTFEable!( { assert(to!string(1uL << 62) == "4611686018427387904"); assert(to!string(0x100000000) == "4294967296"); assert(to!string(-138L) == "-138"); }); } If this code does not run at CTFE, then a static assert triggers. This is currently "package", but it proves that what you asked for is not only possible, it is implemented *and* used in phobos. So either duplicate locally, or file an ER to make it public I guess.
Aug 05 2013
On Monday, 5 August 2013 at 16:50:12 UTC, monarch_dodra wrote:On Monday, 5 August 2013 at 14:02:06 UTC, Dicebot wrote:Considering your, example, you can always do `static assert(to!string(1uL << 62) == "4611686018427387904");` What is the crucial difference?Use case?The use case is simply checking that your functions can be CTFE'd, and that they produce the correct result.
Aug 05 2013
On Monday, 5 August 2013 at 17:13:52 UTC, Dicebot wrote:On Monday, 5 August 2013 at 16:50:12 UTC, monarch_dodra wrote:Well, the "crucial" difference is that this tests a single expression, and not an entire block. For example, the simple test that int.init is 0: static assert({int i; assert(i == 0;}); This doesn't work. You'd have to write: static assert({int i; assert(i == 0; return 1;}()); or static assert({int i; assert(i == 0);}(), 1); Both of which are a bit combersome. "assertCTFEable" allows testing that the *block* will actually will compile and ctfe run conveniently.On Monday, 5 August 2013 at 14:02:06 UTC, Dicebot wrote:Considering your, example, you can always do `static assert(to!string(1uL << 62) == "4611686018427387904");` What is the crucial difference?Use case?The use case is simply checking that your functions can be CTFE'd, and that they produce the correct result.
Aug 05 2013
On Monday, 5 August 2013 at 17:30:38 UTC, monarch_dodra wrote:static assert({int i; assert(i == 0;});enum i; static assert(i == 0); I am really struggling to understand the use case. D has a tool to force CTFE execution - `enum`. It has a tool for compile-time checks - `static assert`. Any possible compile-time test can be expressed via those. All assertCTFEable or similar tool adds is ability to save on some `static` markers.
Aug 05 2013
On Monday, 5 August 2013 at 18:15:22 UTC, Dicebot wrote:On Monday, 5 August 2013 at 17:30:38 UTC, monarch_dodra wrote:You are working around the argument. The point is that some calls simply can't be reduced to a single call. How would you deal with testing "parse" then? assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); }); The point is that you can write "native" runtime code, and then only CTFE test it once. It brings more than just "saving" on markers. What about, for example: assertCTFEable!({ int i = 5; string s; while (i--) s ~= 'a'; assert(s == "aaaaa"); }); And still, all of these are just simple cases.static assert({int i; assert(i == 0;});enum i; static assert(i == 0); I am really struggling to understand the use case. D has a tool to force CTFE execution - `enum`. It has a tool for compile-time checks - `static assert`. Any possible compile-time test can be expressed via those. All assertCTFEable or similar tool adds is ability to save on some `static` markers.
Aug 05 2013
On Monday, 5 August 2013 at 18:27:02 UTC, monarch_dodra wrote:...Saying "test CTFE function that mutates its arguments" would have been perfectly enough for me :) Okay, that makes sense, thanks for the explanation.
Aug 05 2013
On 08/05/13 20:27, monarch_dodra wrote:On Monday, 5 August 2013 at 18:15:22 UTC, Dicebot wrote:static assert({ int i = 5; string s; while (i--) s ~= 'a'; return s == "aaaaa"; }()); etc arturOn Monday, 5 August 2013 at 17:30:38 UTC, monarch_dodra wrote:You are working around the argument. The point is that some calls simply can't be reduced to a single call. How would you deal with testing "parse" then? assertCTFEable!({ string s = "1234abc"; assert(parse! int(s) == 1234 && s == "abc"); }); The point is that you can write "native" runtime code, and then only CTFE test it once. It brings more than just "saving" on markers. What about, for example: assertCTFEable!({ int i = 5; string s; while (i--) s ~= 'a'; assert(s == "aaaaa"); }); And still, all of these are just simple cases.static assert({int i; assert(i == 0;});enum i; static assert(i == 0); I am really struggling to understand the use case. D has a tool to force CTFE execution - `enum`. It has a tool for compile-time checks - `static assert`. Any possible compile-time test can be expressed via those. All assertCTFEable or similar tool adds is ability to save on some `static` markers.
Aug 05 2013
On 8/5/2013 11:27 AM, monarch_dodra wrote:What about, for example: assertCTFEable!({ int i = 5; string s; while (i--) s ~= 'a'; assert(s == "aaaaa"); });I don't believe that is a valid use case because the code being tested is not accessible from anything other than the test.
Aug 18 2013
On Sunday, 18 August 2013 at 20:35:06 UTC, Walter Bright wrote:On 8/5/2013 11:27 AM, monarch_dodra wrote:I'm not sure what that means. Isn't that the case of all unittest? In any case, I was just saying the above template was enough for our needs, and that I don't think a language solution is in order. Also, I think the: //---- unittest { void dg() { BODY OF UNITTEST } dg(); //test runtime assertCTFEable!dg; //test compiletime } //---- usecase makes it useful. Although arguably, you could just: //---- unittest { bool dg() { BODY OF UNITTEST return true; } dg(); //test runtime enum a = dg(); or static assert(dg); } //---- But really, I'm just saying why type that when the template does it pretty well for us, while being self-docuenting?What about, for example: assertCTFEable!({ int i = 5; string s; while (i--) s ~= 'a'; assert(s == "aaaaa"); });I don't believe that is a valid use case because the code being tested is not accessible from anything other than the test.
Aug 19 2013
On Monday, 5 August 2013 at 16:50:12 UTC, monarch_dodra wrote:This is currently "package", but it proves that what you asked for is not only possible, it is implemented *and* used in phobos.topic-starter has been asking about _language_ feature and my answer was related to this possible _language_ feature. Existence of some template in Phobos does not prove anything here.
Aug 05 2013
On Monday, 5 August 2013 at 17:15:34 UTC, Dicebot wrote:On Monday, 5 August 2013 at 16:50:12 UTC, monarch_dodra wrote:Well, it's not about *proving* anything :/ Technically, the question asked was: "Are compile-time unittests possible in D?", so I'm not even sure the question *was* strictly about language. But even if someone asks if a "language" can *do* something you *have* to take into account what the library can do. For example, D doesn't have "native" octals because they are library implemented. Does this mean that "D doesn't have octals" ? So sure, I guess that strictly speaking, no, D language doesn't have static unittests. However, when someone asks the question, if you just answer "No" without pointing out that the language allows this semantic: version(unittest) assertCTFEAble!({ //YOUR CODE HERE }); Then I believe you are giving an incomplete answer.This is currently "package", but it proves that what you asked for is not only possible, it is implemented *and* used in phobos.topic-starter has been asking about _language_ feature and my answer was related to this possible _language_ feature. Existence of some template in Phobos does not prove anything here.
Aug 05 2013
On Monday, 5 August 2013 at 17:38:22 UTC, monarch_dodra wrote:So sure, I guess that strictly speaking, no, D language doesn't have static unittests. However, when someone asks the question, if you just answer "No" without pointing out that the language allows this semantic: version(unittest) assertCTFEAble!({ //YOUR CODE HERE }); Then I believe you are giving an incomplete answer.Well, the problem is, D does have static unit-tests in a form of `static assert`. But topic starter has immediately provided an example that shows that his understanding of "static unit-tests" is different one, making it pretty hard to reason about proper alternative. Even assertCTFEAble does not _exactly_ match what was asked here. Thus I feel the need to first ask about specific use case and only then propose any real solutions. So, yes, of course, it is incomplete - because question is incomplete and requires further clarification. Which is the main point.
Aug 05 2013
On Monday, 5 August 2013 at 18:21:37 UTC, Dicebot wrote:On Monday, 5 August 2013 at 17:38:22 UTC, monarch_dodra wrote:Alright. I tend to try to give as much information as possible in answers, even when the question isn't completely clear, or it was not exactly what was asked. With some luck, I can provide enough information to get the question answered, or give enough background to provide better understanding. This may or may not be the best thing to do, and sometimes it may indeed be better to stop and ask for clarification. I'll agree my answer is not 100% exact, but I feel it does bring something to the conversation. In any case, while it was a reply/quote to what you said, it was not meant as a rebutal to what you were saying.So sure, I guess that strictly speaking, no, D language doesn't have static unittests. However, when someone asks the question, if you just answer "No" without pointing out that the language allows this semantic: version(unittest) assertCTFEAble!({ //YOUR CODE HERE }); Then I believe you are giving an incomplete answer.Well, the problem is, D does have static unit-tests in a form of `static assert`. But topic starter has immediately provided an example that shows that his understanding of "static unit-tests" is different one, making it pretty hard to reason about proper alternative. Even assertCTFEAble does not _exactly_ match what was asked here. Thus I feel the need to first ask about specific use case and only then propose any real solutions. So, yes, of course, it is incomplete - because question is incomplete and requires further clarification. Which is the main point.
Aug 05 2013
On Monday, 5 August 2013 at 12:25:36 UTC, Bosak wrote:Are compile-time unittests possible in D? Maybe something like: static unittest { assert(2 == 1 + 1); } So that every assert in the unittest is translated to static assert. And no normal asserts to be allowed in static unittest? So the above code would be executed at compile time and translated to: unittest { static assert(2 == 1 + 1); }Not exactly as you describe but you can do unit tests for CTFE functions. Have a look at this thread: http://forum.dlang.org/thread/ks1brj$1l6c$1 digitalmars.com -- /Jacob Carlborg
Aug 05 2013
On 8/5/13, Bosak <bosak gmail.com> wrote:Are compile-time unittests possible in D? Maybe something like: static unittest { assert(2 == 1 + 1); }Nope. Interestingly, in git-head we now have the getUnitTests trait, however this won't allow us to call the tests at compile time, I get back: Error: __unittestL5_1 cannot be interpreted at compile time, because it has no available source code This trait is fairly new, so maybe we could expand on this to allow invoking the tests at compile time. Note of course that fundamentally not all tests can be executed at compile-time (e.g. any kind of use of files makes them non-CTFE-able)
Aug 05 2013
On 2013-08-05 16:24, Andrej Mitrovic wrote:Nope. Interestingly, in git-head we now have the getUnitTests trait, however this won't allow us to call the tests at compile time, I get back: Error: __unittestL5_1 cannot be interpreted at compile time, because it has no available source code This trait is fairly new, so maybe we could expand on this to allow invoking the tests at compile time.It does work, at least when I added it: http://forum.dlang.org/thread/ks1brj$1l6c$1 digitalmars.com -- /Jacob Carlborg
Aug 12 2013
On 8/12/13, Jacob Carlborg <doob me.com> wrote:It does work, at least when I added it: http://forum.dlang.org/thread/ks1brj$1l6c$1 digitalmars.comHmm that does work! Looks like I must have hit some kind of bug somewhere, but I lost the sample code that failed. I'll report it if I run into it again.
Aug 12 2013
monarch_dodra got my point. So a static unittest is just like a normal one, but it will be executed in compile time. And every assert in it is a static assert. They will be only used to test CTFE's results and to insure that all constants are initialized correctly. I really think that this should be added to the language, because it doesn't break stuff and it is useful. And the 'static' keyword is already used in many places like module imports and ifs.
Aug 17 2013
On 8/17/13, Borislav Kosharov <boby_dsm abv.bg> wrote:I really think that this should be added to the language, because it doesn't break stuff and it is useful. And the 'static' keyword is already used in many places like module imports and ifs.Have you tried using the new getUnitTests trait in the git-head version? If not it will be in the 2.064 release. Btw such a 'static unittest' feature is certainly going to break code because static can be applied as a label, for example: class C { static: void foo() { } unittest { /* Test the foo method. */ } // suddenly evaluated at compile-time }
Aug 17 2013
On Saturday, 17 August 2013 at 17:48:04 UTC, Andrej Mitrovic wrote:On 8/17/13, Borislav Kosharov <boby_dsm abv.bg> wrote:Oh I really haven't tough about that. Maybe, I will try this new trait. Or another solution is to add a compiler switch that will try to execute all the tests during compilation or something.I really think that this should be added to the language, because it doesn't break stuff and it is useful. And the 'static' keyword is already used in many places like module imports and ifs.Have you tried using the new getUnitTests trait in the git-head version? If not it will be in the 2.064 release. Btw such a 'static unittest' feature is certainly going to break code because static can be applied as a label, for example: class C { static: void foo() { } unittest { /* Test the foo method. */ } // suddenly evaluated at compile-time }
Aug 18 2013
On Sunday, 18 August 2013 at 16:15:30 UTC, Borislav Kosharov wrote:On Saturday, 17 August 2013 at 17:48:04 UTC, Andrej Mitrovic wrote:Well, that assumes all your code is ctfe-able... I've taken to doing something along the line of: unittest { void dg() { BODY OF UNITTEST } dg(); //test runtime assertCTFEable!dg; //test compiletime } It's a quick and easy way of testing both code paths, with minimal duplication and hassle.On 8/17/13, Borislav Kosharov <boby_dsm abv.bg> wrote:Oh I really haven't tough about that. Maybe, I will try this new trait. Or another solution is to add a compiler switch that will try to execute all the tests during compilation or something.I really think that this should be added to the language, because it doesn't break stuff and it is useful. And the 'static' keyword is already used in many places like module imports and ifs.Have you tried using the new getUnitTests trait in the git-head version? If not it will be in the 2.064 release. Btw such a 'static unittest' feature is certainly going to break code because static can be applied as a label, for example: class C { static: void foo() { } unittest { /* Test the foo method. */ } // suddenly evaluated at compile-time }
Aug 18 2013