c#:
I just got a TypeInitializationException exception. Why it is a common cause for this? The InnerException is System.FormatException, although I don't see anything requesting something to be formatted. I'm trying to invoke the use of a class, to force its static c'tor to run, which will run its unit test. Is there a good way to force all class's static c'tors to be run on startup? Zytan
[quoted text, click to view] > Is there a good way to force all > class's static c'tors to be run on startup?
No simple way. You could perhaps have a dummy static method (NOP, no in-lining) marked with a known bespoke attribute; use reflection to scan for this over all classes and invoke? This would (under C# rules; the CLR actually supports more complex loading strategies) force the static ctor (if one) to execute... Or create and instance of the class if default ctors are available... but nothing simple. Of course, you could simple list the necessary dummy static methods in the top of Program.cs / global.asax - would be more efficient at runtime, but higher maintenance. Marc
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > I just got a TypeInitializationException exception. Why it is a > common cause for this? > > The InnerException is System.FormatException, although I don't see > anything requesting something to be formatted.
I'd have a look at the stack traces carefully - they should show which class is involved. [quoted text, click to view] > I'm trying to invoke the use of a class, to force its static c'tor to > run, which will run its unit test. Is there a good way to force all > class's static c'tors to be run on startup?
Well, you can use Assembly.GetTypes() to get all the types in the assembly, then use Type.TypeInitializer to get a ConstructorInfo which you can then Invoke. However, that will force any type initializers which have already run to be run again, which could be dangerous depending on what they do! As a side issue, I'm not sure that making static constructors run unit tests is a good idea. I personally put them in a separate assembly and run them with NUnit... -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] > > I just got a TypeInitializationException exception. Why it is a > > common cause for this? > > > The InnerException is System.FormatException, although I don't see > > anything requesting something to be formatted. > > I'd have a look at the stack traces carefully - they should show which > class is involved.
Looking in the stack trace of InnerException, I found this was the problem: string s = SomeMethod(); // can return null or "", or any string. int x = int.Parse("0"+s); Where "0"+s should work if s is null or "" or a non-empty string. Commenting out this code removed the exception. What is wrong witt that code? It runs fine elsewhere. Zytan
[quoted text, click to view] > > Is there a good way to force all > > class's static c'tors to be run on startup? > > No simple way.
Ok, thanks Marc. Your suggestions aren't much different from what I'm doing now. Zytan
[quoted text, click to view] > As a side issue, I'm not sure that making static constructors run unit > tests is a good idea. I personally put them in a separate assembly and > run them with NUnit...
Well, I don't want anything overly complex. NUnit doesn't really even say what it is (how its implemented). I have to download it to find out. I'd be nice if it were explained a little better on the webpage. My projects are small at the moment, so maybe I'll look into NUnit later when I can justify that time, since I can only assume it is rather complex if they can't give a quick explanation right away. Thanks, Zytan
[quoted text, click to view] > > string s = SomeMethod(); // can return null or "", or any string. > > int x = int.Parse("0"+s); > > Well, if it returns "foo" then you'll be trying to parse "0foo" which > will indeed throw an exception.
Yes, that's true. So I need to catch this. Duh. [quoted text, click to view] > This looks like odd code to be running in a static constructor > though...
It's code in a method called by a method, called by a method, etc., that the unit testing method calls, which is invoked by the static c'tor. The unit testing hopefully tests everything the class can do. What I don't get is: Why, when the static c'tor is invoked, why can't I step through the code? NOW I GET IT, this code is being run and it's failing because int.Parse() is throwing the exception. I thought the code wasn't being run, and it was a type initialization failure (something that happens before code is run, which I thought must happen a the start of any function for all local vars or something). But, it IS a type initialization failure, the type is the class. And the whole unit testing and all my code is being run all in one go, without option to step through, which tricked me into believing it wasn't being run, and so I had to resort to strange ideas in order to explain what was happening. OMG. Why can't it just report the exception at the int.Parse() line? Strange. Haha, what a bug. Thanks again! Zytan
[quoted text, click to view] > What I don't get is: Why, when the static c'tor is invoked, why can't > I step through the code?
This only works if I F9 on the static c'tor itself. It won't step into it when it is invoked automatically. [quoted text, click to view] > Why can't it just report the exception at the int.Parse() line?
If you are stepping through the static c'tor execution, via the method above, when an exception it thrown that is not handled, the exception thrown is *still* not reported on the spot. It gets tucked deep away as the InnerException of the TypeInitializationException for the static 'ctor. <sigh> So, yeah, Jon, you are right -- static c'tor are NOT the best place to run unit tests. Now. What's a better place other than using NUnit? Like for a really small project? (no project is too small for unit testing.) Zytan
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > > > I just got a TypeInitializationException exception. Why it is a > > > common cause for this? > > > > > The InnerException is System.FormatException, although I don't see > > > anything requesting something to be formatted. > > > > I'd have a look at the stack traces carefully - they should show which > > class is involved. > > Looking in the stack trace of InnerException, I found this was the > problem: > > string s = SomeMethod(); // can return null or "", or any string. > int x = int.Parse("0"+s); > > Where "0"+s should work if s is null or "" or a non-empty string. > Commenting out this code removed the exception. What is wrong witt > that code? It runs fine elsewhere.
Well, if it returns "foo" then you'll be trying to parse "0foo" which will indeed throw an exception. This looks like odd code to be running in a static constructor though... -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > > As a side issue, I'm not sure that making static constructors run unit > > tests is a good idea. I personally put them in a separate assembly and > > run them with NUnit... > > Well, I don't want anything overly complex. NUnit doesn't really even > say what it is (how its implemented). I have to download it to find > out. I'd be nice if it were explained a little better on the > webpage. My projects are small at the moment, so maybe I'll look into > NUnit later when I can justify that time, since I can only assume it > is rather complex if they can't give a quick explanation right away.
No, NUnit is anything but complex. I strongly recommend that you download TestDriven.NET ( www.testdriven.net) and give it a try. It's *definitely* worth doing unit testing properly instead of in an ad hoc manner where you can't easily run all tests, get all results etc. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > Now. What's a better place other than using NUnit? Like for a really > small project? (no project is too small for unit testing.)
Even for a really small project, I'd use NUnit. Others recommend MbUnit, but I don't know that that's any more suitable for small projects than NUnit is. Once you've used NUnit a few times, you'll think nothing of using it, however small the project. Although I tend to put the tests into a different project, you don't *have* to, if that's more overhead than you want. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] > Even for a really small project, I'd use NUnit. Others recommend > MbUnit, but I don't know that that's any more suitable for small > projects than NUnit is. > > Once you've used NUnit a few times, you'll think nothing of using it, > however small the project. Although I tend to put the tests into a > different project, you don't *have* to, if that's more overhead than > you want.
Ok, NUnit it is. But wait. I consider TWO types of unit testing, something I've conceived myself: 1. run-time unit testing that test a short sample, quickly, that does as much as it can without getting in the way, which is removed for final production. This shows incorrect code immediately on the next run. It's the fastest unit testing feedback possible. 2. indepth testing, overnight testing, that runs for hours, testing everything. This has everything that #1 can't have since it takes too long. Does NUnit do #1 as well? If not, it's not good enough. I thought I should ask, since you said you put your unit testing in another project, implying no run-time unit testing. (by 'run time', I just mean it is run on every execute, preferably at the START, which is why I want to run all my static c'tor on load.) Zytan
[quoted text, click to view] > NUnit is specifically for frequent unit testing.
Ok great! [quoted text, click to view] > It doesn't happen when > you run your application - it happens when you run your tests. That > should happen (IMO) much more often than you start your application.
Ah, I see. Yes, unless you're like me and your application is the unit tests. But, if my app wasn't, and the unit tests were in another project, I can totally see why this test project would be run much more often. It's the *reason* my app is run so often - for testing. [quoted text, click to view] > Running tests should be pretty much as frequent as building - and you > need to write your unit tests appropriately so they run quickly.
As i write code, I test it inside of my app by running it. So, if the unit test project does the testing, then *that's* the code i'll be running all the time. [quoted text, click to view] > Of course, you may decide to have different categories of unit tests, > some of which will take longer to run - but in general, tests which are > run most often are the most useful ones.
I agree. But, the longer tests have value in specific applications. Such as stress testing multithreading apps. I've done that to confirm bugs that should exist during mid-implementation, and confirm (within reason) that they no longer exist once I've solve the problem. I suppose this change of pace is what 'test driven development' is all about? It means I've been doing it for a long time, just not quite on track. Zytan
[quoted text, click to view] > > As i write code, I test it inside of my app by running it. So, if the > > unit test project does the testing, then *that's* the code i'll be > > running all the time. > > I don't like the confusion between test code and real code - and in > particular, the fact that you'll have to get rid of the test code to > build the "release" version means that your tests won't be running > against the real code.
I don't follow what you mean here. I run my unit test in debug and release, but in the final-release, those calls become blank functions (only for speed purposes, if I could run them, and report errors back home, I'd be happy to do this, if it didn't have any side effects of slowing the app). [quoted text, click to view] > For instance, having a static constructor in a class subtly changes the > semantics of the class - see http://pobox.com/~skeet/csharp/beforefieldinit.html > So if you only have a static constructor in a class for test purposes, > you'll be changing the semantics of that class when you remove that > static constructor. I would just leave the static c'tor, and make the unit test function call a blank function (or remove the call). The static c'tor has no unit test code in it, other than the call to the unit test function. [quoted text, click to view] > > I agree. But, the longer tests have value in specific applications. > > Such as stress testing multithreading apps. I've done that to confirm > > bugs that should exist during mid-implementation, and confirm (within > > reason) that they no longer exist once I've solve the problem. > > Yes, that's fine - but they're not unit tests. It's often useful to use > a unit test framework to build/run such tests, but they're not unit > tests.
Hmm? But, they have pretty much the same code. Only the quick unit test differs in cases where I cannot make a quick version of the longer unit test. The longer unit test has everything the quick one has, and more. It has the same function calls, but it calls them more. I fail to see how they aren't exactly the same thing -- unit tests. They test my units. One does a more thorough job. I wish it could do it every compile, but my computer is just not fast enough. So, the quick test is more unlike a unit test than the long test, if either, since it doesn't do the full job. Are you saying there's a strict definition of what 'unit test' means? [quoted text, click to view] > Test driven development means more than just writing unit tests for > code. It means writing the tests before the code exists in the first > place. The effect of that is that you write code which is always > testable, and your interfaces tend to be usable, because they're driven > by what the caller wants to do, rather than what the class wants to > expose.
Yes, actually, I knew that. I had read up on it a bit. It's like coding backwards, a bit. And I haven't been doing that at all. Zytan
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote:
<snip> [quoted text, click to view] > Does NUnit do #1 as well? If not, it's not good enough. I thought I > should ask, since you said you put your unit testing in another > project, implying no run-time unit testing. (by 'run time', I just > mean it is run on every execute, preferably at the START, which is why > I want to run all my static c'tor on load.)
NUnit is specifically for frequent unit testing. It doesn't happen when you run your application - it happens when you run your tests. That should happen (IMO) much more often than you start your application. Running tests should be pretty much as frequent as building - and you need to write your unit tests appropriately so they run quickly. Of course, you may decide to have different categories of unit tests, some of which will take longer to run - but in general, tests which are run most often are the most useful ones. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > > NUnit is specifically for frequent unit testing. > > Ok great! > > > It doesn't happen when > > you run your application - it happens when you run your tests. That > > should happen (IMO) much more often than you start your application. > > Ah, I see. Yes, unless you're like me and your application is the > unit tests. But, if my app wasn't, and the unit tests were in another > project, I can totally see why this test project would be run much > more often. It's the *reason* my app is run so often - for testing.
Right. Whereas I only run my application when I want to see "the big picture" rather than to make sure the tests run correctly. [quoted text, click to view] > > Running tests should be pretty much as frequent as building - and you > > need to write your unit tests appropriately so they run quickly. > > As i write code, I test it inside of my app by running it. So, if the > unit test project does the testing, then *that's* the code i'll be > running all the time.
I don't like the confusion between test code and real code - and in particular, the fact that you'll have to get rid of the test code to build the "release" version means that your tests won't be running against the real code. For instance, having a static constructor in a class subtly changes the semantics of the class - see http://pobox.com/~skeet/csharp/beforefieldinit.html So if you only have a static constructor in a class for test purposes, you'll be changing the semantics of that class when you remove that static constructor. [quoted text, click to view] > > Of course, you may decide to have different categories of unit tests, > > some of which will take longer to run - but in general, tests which are > > run most often are the most useful ones. > > I agree. But, the longer tests have value in specific applications. > Such as stress testing multithreading apps. I've done that to confirm > bugs that should exist during mid-implementation, and confirm (within > reason) that they no longer exist once I've solve the problem.
Yes, that's fine - but they're not unit tests. It's often useful to use a unit test framework to build/run such tests, but they're not unit tests. [quoted text, click to view] > I suppose this change of pace is what 'test driven development' is all > about? It means I've been doing it for a long time, just not quite on > track.
Test driven development means more than just writing unit tests for code. It means writing the tests before the code exists in the first place. The effect of that is that you write code which is always testable, and your interfaces tend to be usable, because they're driven by what the caller wants to do, rather than what the class wants to expose. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] Zytan <zytanlithium@yahoo.com> wrote: > > > As i write code, I test it inside of my app by running it. So, if the > > > unit test project does the testing, then *that's* the code i'll be > > > running all the time. > > > > I don't like the confusion between test code and real code - and in > > particular, the fact that you'll have to get rid of the test code to > > build the "release" version means that your tests won't be running > > against the real code. > > I don't follow what you mean here. > > I run my unit test in debug and release, but in the final-release, > those calls become blank functions (only for speed purposes, if I > could run them, and report errors back home, I'd be happy to do this, > if it didn't have any side effects of slowing the app).
It still means that the code is different at test time to normal release. [quoted text, click to view] > > For instance, having a static constructor in a class subtly changes the > > semantics of the class - see http://pobox.com/~skeet/csharp/beforefieldinit.html > > So if you only have a static constructor in a class for test purposes, > > you'll be changing the semantics of that class when you remove that > > static constructor. > > I would just leave the static c'tor, and make the unit test function > call a blank function (or remove the call). The static c'tor has no > unit test code in it, other than the call to the unit test function. Then you're getting a (slight) performance penalty for having a static constructor in every class. It means the JIT can't perform some optimisations when accessing static members of the class. [quoted text, click to view] > > > I agree. But, the longer tests have value in specific applications. > > > Such as stress testing multithreading apps. I've done that to confirm > > > bugs that should exist during mid-implementation, and confirm (within > > > reason) that they no longer exist once I've solve the problem. > > > > Yes, that's fine - but they're not unit tests. It's often useful to use > > a unit test framework to build/run such tests, but they're not unit > > tests. > > Hmm? But, they have pretty much the same code. Only the quick unit > test differs in cases where I cannot make a quick version of the > longer unit test. The longer unit test has everything the quick one > has, and more. It has the same function calls, but it calls them > more. I fail to see how they aren't exactly the same thing -- unit > tests. They test my units. One does a more thorough job. I wish it > could do it every compile, but my computer is just not fast enough. > So, the quick test is more unlike a unit test than the long test, if > either, since it doesn't do the full job. > > Are you saying there's a strict definition of what 'unit test' means?
If it's just testing a single unit, that's fine - sorry, your previous description of "stress testing multithreading apps" suggested that it was testing the whole application, rather than a single class. [quoted text, click to view] > > Test driven development means more than just writing unit tests for > > code. It means writing the tests before the code exists in the first > > place. The effect of that is that you write code which is always > > testable, and your interfaces tend to be usable, because they're driven > > by what the caller wants to do, rather than what the class wants to > > expose. > > Yes, actually, I knew that. I had read up on it a bit. It's like > coding backwards, a bit. And I haven't been doing that at all.
It takes a while to get used to, and it's not *always* suitable, but it can produce fabulous results. -- Jon Skeet - <skeet@pobox.com> http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
[quoted text, click to view] > > I run my unit test in debug and release, but in the final-release, > > those calls become blank functions (only for speed purposes, if I > > could run them, and report errors back home, I'd be happy to do this, > > if it didn't have any side effects of slowing the app). > > It still means that the code is different at test time to normal > release.
Very true. While it shouldn't matter, I have seen bugs where independent pieces of code have dependencies, and it could just be where the first static c'tor is run. But, hopefully, the unit testing should solve those exact problems before they could become a problem. I thought maybe the unit test could be left in, as an even faster version of the normal one that is run on every execute. Something that takes 1/100th of a second, or 1/10th of a second maximum. And it could report to home base if there's an error, and continue on. I've never liked that debug code disappears at release time, and there's release specific code that will handle as many errors as it can, since it's too late to call Debug.Assert when it's on the customer's machine. It'd be nice if something, anything, could be done, at least during the first 0.1 seconds of launch to test a few things, and report home about possible issues. This is something I highly doubt anyone does. [quoted text, click to view] > > I would just leave the static c'tor, and make the unit test function > > call a blank function (or remove the call). The static c'tor has no > > unit test code in it, other than the call to the unit test function. > > Then you're getting a (slight) performance penalty for having a static > constructor in every class. It means the JIT can't perform some > optimisations when accessing static members of the class.
Oh, ok. Zytan
[quoted text, click to view] Zytan wrote: >>> I run my unit test in debug and release, but in the final-release, >>> those calls become blank functions (only for speed purposes, if I >>> could run them, and report errors back home, I'd be happy to do this, >>> if it didn't have any side effects of slowing the app). >> It still means that the code is different at test time to normal >> release. > > Very true. While it shouldn't matter, I have seen bugs where > independent pieces of code have dependencies, and it could just be > where the first static c'tor is run.
C# should not have much of the classic C/C++ unpredictable behavior for various memory related bugs. But there are a fundamental problem proving that the the unit test code itself is the only difference between what you tested and what you put in production.
Don't see what you're looking for? Try a search.
|