|
|
Comments and Discussions
|
|
 |
|

|
Thanks for such a wonderful article. Thanks buddy
Albert
Have a date for free
|
|
|
|
|
|

|
So long i was searching for anything similar.
Thanks & Congratulations
Kind Regards.
tutoriales photoshop
|
|
|
|
|
|

|
Hi,
I tried the sources from your site still there is a problem with them there is no disp.xls so a FileNotfound exception pops up.
It would be nice to have it.
Also noticed that reverse tests for xml utilities fails so I wonder if this is ok or not . I expected them to pass as long tey are designed for AUT and are included there . For such a nice article I was expecting a finished /complete AUT, or at least some comments/notes or a page near download link ?
Signed: Anonymous
|
|
|
|
|

|
You presented this topic very well. Good work! This is definitely a 5 out of 5 rating. However, why be limited to proprietary language designed for a specific operating system?
As far as testing patterns, I only use a few of the patterns you listed in the following percents: Pass/Fail=75%, Multi-threading=20%, Data Driven=5%. And, the multi-threading tests as well as the data driven tests are just variations of the pass/fail test. So, they are really all pass/fail. The code i use to repeat threading and data driven test patterns is just block copied. I never took the time to make a reusable framework, since the code is rather simple and small such that copying is no big deal.
Another thing is that unit tests serve as example code, so as much as possible, tests are concrete examples that can be cut and pasted into project code. I would avoid hiding things like initialization, iteration, and life cycle in some sort of testing framework because that would obfuscate the code. One of my primary motivations as I am writing test cases, is to present simple "hello world" scenarios completely contained within one function call. I prefer these test cases for documentation purpose over paragraphs of comments embedded in header files, and even over doxygen HTML files.
For an open source project to truly be useful, stick to ANSI C++, and platform independent code. I like unit testing, and find that it makes portability easier. I can develop on one platform, and run unit tests on the other platforms (Windows versions, Linux versions, BSD, Mac).
A fancy GUI is always kinda cool, but totally unnecessary for unit testing in my opinion. My tests print a dot '.' for each success, and display a file/line/message for errors. That's all i need.
|
|
|
|
|

|
Great article - I'll pass it on to my organisation's practice group as suggested reading.
I think this needs another pattern called testability. This refers to the way Systems Under Test (SUT) should be written to make them testable. This includes:
- separating distinct functionality into separate functions
- Diagnostic patterns
- Inspection patterns
- exposing otherwise private functions available to the test harness
- mock plugs
- state indicators
- etc...
|
|
|
|

|
The following test patterns should be added for security purposes
Access Control (includes deny as default and tests for least privilege
Impersonation (check for failed impersonation)
Stack Overruns
Heap Overruns
Buffer Overflows
Buffer Underflows
Format Strings (things like "%s", submitted in string
Name-Squatting
Cross Site Scripting
SQL Injection
OS Command Injection
Path Traversal
Meta Characters
NULL Bytes
Canonicalization - case sensitivity
Canonicalization - unicode
Canonicalization - url encoding
Session Replay
|
|
|
|

|
Thanks for writing this article Marc (even the whole series), it is quite thought provoking. This one is especially bold, so my hat's off to you.
I must admit to feeling confused about a couple things. For one, I'm not sure that the most useful unit tests can be captured by a pattern beyond the Simple-Test pattern. (Actually in a sense don't all unit tests fall into the Simple-Test pattern??) Second, I think these patterns are at different levels of abstraction -- which is fine, but I had to realize that to get more comfortable with them.
In my mind, your unit tests should test/assert that a class (or component etc) performs the way in which you need it to perform. Because of this the form of your unit test is dependent on how your class actually works. If a class is enumerable and transactional, then it will take unit tests which test those qualities. In this sense I see the motivation for the "Data Transaction Patterns" and "Collection Management Patterns" and "Constraint Data" patterns etc. So for any common implementation idioms, there is going to be such a corresponding unit testing "pattern." For example, does your class support casting operations? Maybe that needs a unit testing pattern. Do groups of your classes have ways to traverse between them? Maybe those need an object traversal unit testing pattern. Thinking about common behaviors that components support, there are probably many more such unit testing patterns for them.
But then there are the peculiar behaviors of the classes and components in a system, and to test these is exactly where I think none of those patterns is going to help you. I may want to unit test my fraction class by creating an object with numerator 3 and denominator 4, then assure that this object correctly casts to a 0.75 float. Which pattern is this? I guess it is just the Simple-Test pattern. Now from reading the article I might think that such tests are not very useful, but aren't many extremely useful tests of the particular behaviors of your classes going to be of this variety? Such tests do not follow any interesting pattern (i.e., they are not generalizable), because the nature of the test is a reflection of the peculiar design of one class, which is reflecting a particular requirement. I think some of my most useful unit tests (useful in terms of both helping me tweak the class's design, and in finding bugs created by refactors) have been of this variety. Or to put it more strongly, I think if one's unit tests do not contain such pattern-defying, application specific tests, then they probably aren't doing you much good.
Many of the other patterns you describe seem to be at a higher level of abstraction. They are not "test this programming idiom" (such as collection functionality or db transactionality), but (sometimes) "test in this way", such as the Simple-Test-Data pattern or the Simulation Patterns. For me it is clarifying to segregate your patterns on this basis.
Brad Williams
|
|
|
|

|
First and formost I write unit tests for my code. Why? Because I get that warm fuzzy when everything passes. Does that mean my code is without flaws? No, I dont think code will ever be without flaws until we get to the Star Trek level of programming (Just hit that button and you've reconfigured the shields to emmit a deadly beam). However I do believe that I have caught many bugs I've introduced into the system with my unit tests saving me invaluable time.
In one of the mentioned articles someone stated that Unit testing is a maintenance problem when refactoring is concerned. I suppose that is one way to look at it. However, imagine you change the subsystem of your project consisting of 10,000 lines of code. Now because you the developer dont believe there has been enough time and money allocated to testing havent done much QA yourself. Do you really feel more comfortable that you didnt have to change all that unit test code? Now all the changes have been implemented you've found that half the system doesnt work anymore. Where do you begin? You've spent the last 3 hours getting the code built, the machine reconfigured and installing the software just to find out most of it doesn't work. Dont think this can happen? I've been at companies where it happened weekly. The reason? "We dont have time to write the unit tests." was the anwser given. From a logical standpoint it doesn't make any sense. It's very similar to people that speed down the roads thinking it will get them faster, only to be stuck at the next stop light for 5 minutes while all the traffic you flew by catches up to you. Where as you could have plotted a shorter route with less stop lights which have been much easier then being fustrated at the end because nothing worked. One way or another you will end up spending more time and money for code that isnt tested.
The principal behind automated unit testing is the 'automated part'. The computer does the testing. While you did write the tests, the computer will ensure that the test is run the same way every time. QA with people is at best haphazerdous. How do you ensure that the QA person is going to test version 3.0 of your product the same way as the 3.1 version? If you can't ensure this then the previous tests are meaningless when the new version is released, yet we are somehow confident that the product didnt change _that much_.
Some also believe that unit testing can be used to design the interface and contract of a unit with the test itself without first writing the underlying code. Do you ever sit there and think about how your new class is going to work? Or what it's interface should look like? You ever find yourself imaging what it would be like to use the new class. You may not realize it but you were already doing the tests first. You are doing them in your head. Instead of sitting back and visualizing how the class will act, write it down in a form of a unit test. Then it will be captured. While you are writing the test you will more than likely find that you need to change some aspects of your interface to make it more user friendly and be more autonomous.
The fundamental problem with unit testing is the ease of use. For some that are in the spirit they can bypass the tediousness of writing the tests. Others give up because it distracts them from what they really want to do.
To know how fun and usefull writing these test can be, download Eclipse and use the built-in JUnit functionality. I believe this to be the best integrated unit testing framework as of yet. Having to run a 3rd party utility outside of your beloved notpad or IDE is not something anyone looks forward too. I believe the people of the Visual Studio (btw I love Visual Studio) world will soon find the place for unit testings in their lives when there is a more cohesive unit testing framework built into there favorite IDE.
Imagine if you were punished for writing buggy code. You wrote a piece of software that crashed and corrupted the user's data files and you were sentenced to jail for 5 years. I bet you would be more careful of how you test your code. This is what certified Engineer's face when they sign the Engineer's oath. They are legally obligated to build safe and working products whether it be brigdes, houses and the like. This field more often then not rewards developers for building buggy code. Really, think about it. You are hired to build a product for a company, once completed, you are continually paid to 'fix' the product and make it better. Bugs are taken for granted in a product. The idea subconsiously is to find the right mixture of bugs and working code so that you aren't fired, then it's a golden road to continually fixing your own code and getting paid for it. How about that?
-
Andrew T Finnell
Active Solutions LLC
andrew@activesol.net
|
|
|
|

|
Andrew,
I really agree with you about the benefits of solid IDE integration. As you say, Eclipse is fantastic! I've been working on both a large C++/COM project and a Java server side web system over the last few months. I can't get over how different my approach is to both projects.
I believe in the value of unit tests, and I push the envelope of completeness on the Java side. In C++ I still believe, I use CppUnit to try to get there, but the pain threshold remains just a little too high. It has to become part of the basic development flow, like the edit/compile/crash/debug/crash/debug/crash/debug cycle is.
In Java, with proper unit tests in place, I find the debugger sitting idle most of the time. In C++ it's in use far more frequently. That's partly a language difference, but it's also largely a stylistic difference brought on by the ease of unit testing in the Java/Eclipse environment.
Stephen Owens
Corner Software
|
|
|
|

|
Andrew T. Finnell wrote:
Imagine if you were punished for writing buggy code. You wrote a piece of software that crashed and corrupted the user's data files and you were sentenced to jail for 5 years. (...) How about that?
Great. Now you just need to find a legal definition for bug.
Perl combines all the worst aspects of C and Lisp: a billion different sublanguages in one monolithic executable. It combines the power of C with the readability of PostScript. -- Jamie Zawinski
|
|
|
|

|
He he, yeah that would probably keep you out of trouble for years to come.
-
Andrew T Finnell
Active Solutions LLC
andrew@activesol.net
|
|
|
|

|
I'm all for better testing and defined testing processes. I'm the first to admit that I don't do enough myself.
We in the SD business have a real problem, though. Management and customers rarely understand the importance of testing (from a time and money perspective) at least until something goes wrong. Developers are also doing a poor job (in general) of delivering well tested applications. Some developers will say that if a customer is not willing to pay for testing, they won't do business with them. That's fine when working in a sellers market, and especially when working with larger clients, but when you're in a buyers market or dealing with mostly small firms, this is a serious problem.
In my mind, what is needed, is a much better development platform, better devlopment practices and less testing. The reality is that much of the testing methodologies being employed cannot identify problems in a real world situation, especially when working with vastly distributed systems, web applications, etc. I am not saying testing is bad, quite the contrary, but I believe that testing should lead to better development and less testing, not the same development and more testing and more seemless testing.
Many of the tests are targeted at testing boundary conditions, ranges, null handling, etc. In my mind all of this testing should be dealt with completely through declarative specifications within and without the code. As an example, consider the function protoype below (C++ style).
int ComputeDistance(LPCTSTR lpszZipCode1, LPCTSTR lpszZipCode2);
This is a very simple function, but it leaves open to guess lots of details. First of all, is the return value in miles, KM, meters???? Second, can lpszZipCode1 or 2 be NULL. A better way to write this is by providing actual class types to accomodate the data passed and returned.
DistanceInMiles ComputeDistance(ZipCode ZipCode1, ZipCode ZipCode2);
This is better, but puts a burden on the developer to build lots of tiny classes. Another way this could be done is declaratively:
int ComputeDistance(LPCTSTR lpszZipCode1, LPCTSTR lpszZipCode2)
:: return is Distance, Miles, Not Nullable, Positive or Zero,
:: lpszZipCode1 is 5 digits, numeric, Not Nullable
:: lpszZipCode2 is 5 digits, numeric, Not Nullable
By declaring the meaning of parameters and return types (and other details if desired), a runtime can test inputs/outputs and throw exceptions before the function is executed. Add this to runtime automated instrumentation and logging, automated test tools and many testing problems are resolved. A validator could be written to interpert declarations for validity, possibly by comparing to known norms, etc.
I would add, that the second example I gave should also be doable, because I would be able to wrap the declarative constratints into a reusable class. Some of this can be done with templates and generic programming, but not all of it. Eifel supports a form of what I am talking about, design-by-contract, but I don't know all the details of how it works.
Obvoiusly, declarative programming does not solve every problem, far from it. BUT, it is a progressive RESULT of testing, instead of just progressing testing.
|
|
|
|

|
Matt Gullett wrote:
Obvoiusly, declarative programming does not solve every problem, far from it. BUT, it is a progressive RESULT of testing, instead of just progressing testing.
That is true and certainly helpful. But you move the problem. In declarative programming you then need to test the declarations. Remember Ariane?
|
|
|
|

|
Stephan Meyn wrote:
In declarative programming you then need to test the declarations.
Indeed you do. MyXaml Lint[^]
Marc
|
|
|
|

|
First of all, I want to thank Marc for doing an excellent job on this article. This is one of many articles he has written that are must reads for any good software developer. What I like most about Marc's articles is that he usually comes up with some new ideas that are worthwhile and thought provoking.
I would like to think of these "Test Patterns" more like "Best Practices" in our testing efforts. Like many of the popular design patterns, we read about these patterns and realize that we have been using them without even realizing it. We just needed someone smart enough (like Marc) to come along to describe it, illustrate it, and attach a name to it. As I was reading this article, I was saying to myself "ooohhhh yeeeeaaaa, I have used this pattern in my testing". Did any of you have this same experience?
As I was reading about all these test patterns that I probably should be using (by the way Marc, thanks for making feel guilty about not testing like I should), I asked myself the following question over and over again "which of these test patterns are an absolute must in my development efforts". I wish I could do them all, but I just don't have time (sound familiar); so I am curious, how many of these test patterns are developers using. Which of these test patterns are absolutely essential to the success of a software development project?
Last but not least, what would it take to motivate a developer to use more of these test patterns on their own software development projects? I know what your probably going to say, more time and more money!!! I myself have discovered a few tricks, and have changed the way I develop software so that I have enough time to do more testing and use more of the test patterns that Marc is talking about in this article. Marc has suggested a few ideas in his article that are worth considering.
Interested in your feedback and experiences,
Kent
|
|
|
|

|
(stream of unconsciousness warning)
I think it is practical, actually. As suggested in another comment, automated testing of certain types of objects (IEnumerator, not IEnumerable, etc) can be made part of the build, as it should. Also, having a catalog of testable things and the ways in which they can be tested can give good cues for the design of new things.
As for which are essential? That of course is up to the project. Given the nature of the work I've had to perform over the last couple years, anything involving collections is fair game, as is object persistence and application state. For me (and I imagine most), this is the typical application model and, in my experience, testing is at best hand-held and inconsistent.
For C# development, NUnit strikes me as a fairly good way for automated testing. It has some improvements that could be made for IDE integration, though, to make it less hands-on, and always used (at compile-time, for instance -- one less click). The idea of automatic testing of classes that conform to an interface would be a great start. I think the biggest impediment is getting people to take the time to devise these tests, and once the tests are created, getting the data to use for them.
.....
What I'd *really* like is to have pattern support in the programming language, or at least the framework. C# has delegate: Singleton would be reasonable to add, and IFactory could be added to the framework.
Bridges and Adapters could be cobbled together, at least as a type of object that you initialize with knowledge of the classes in question; I think they'd need language-level support to be compile-time checked. Perhaps databinding would be a good route?
|
|
|
|

|
Testing is great in theory, but it is difficult at best to get customers to pay for the initial code let alone the 40% overhead for unit tests. Unfortunately a lot of customers only look at the cosmetics and unit testing does not cover GUIs, they don't often see under the hood.
I found unit testing useful on critical parts of an application, but for most part a diligent step through the code and/or development of prototyped components are just as effective.
The patterns you have described look great on paper but as you say hide the complexity and difficulties one can have simply designing and defining test criteria especially with asynchronous processes. Due to the dynamic nature of programming, one may destroy wholesale sections of code: if an array of tests are created around that code you have the extra overhead of removing the tests or redesigning them to accommodate the new coding.
To sum up, the hardest part is working out that balance of what needs testing and keeping a very tidy house when developing the tests so that it is easy to manage the tests.
(It would also be useful if you could try to demonstrate say a small asynchronous app against the patterns you have described, and maybe a scope change effect on the tests with analysis of the change impact.)
My two bobs worth..
|
|
|
|

|
Stuart Kinnear wrote:
Testing is great in theory, but it is difficult at best to get customers to pay for the initial code let alone the 40% overhead for unit tests.
Yup. But what the customer doesn't realize is that he's paying for testing one way or the other. The question is, can unit testing effectively replace some of the QA process?
Stuart Kinnear wrote:
Unfortunately a lot of customers only look at the cosmetics and unit testing does not cover GUIs, they don't often see under the hood.
Here you hit right on the end. This is an issue that I'm trying to get my arms around, because not being able to interact at the GUI level with unit testing is a serious drawback, IMHO.
Stuart Kinnear wrote:
if an array of tests are created around that code you have the extra overhead of removing the tests or redesigning them to accommodate the new coding.
Exactly. Like documentation, unit tests become a maintenance liability. This is supposed to trade off with the time savings they provide. This is like a jellyfish-it squirms and writhes away from your grasp. It's impossible to prove one way or the other, that unit testing saves time. I think the only thing that gives some assurance of saving time is the skill of the programmer.
Stuart Kinnear wrote:
(It would also be useful if you could try to demonstrate say a small asynchronous app against the patterns you have described, and maybe a scope change effect on the tests with analysis of the change impact.)
An excellent suggestion!
Thanks for the feedback,
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|

|
Thanks Marc, I feel that you are the only one who has replied so, who has read my comments properly.
I am not saying "don't do unit testing", I am not that shortsighted. In fact I wrote an article a year or two back on unit testing for Microsoft Access in Pinnacle Publishing's Smart Access magazine.
What I am saying however, is that we live in commercial world, therefore it is important to try and judge what impact unit testing will have in terms of time, cost and maintenance.
It is all well and good to set up hundreds of tests, but what of getting the project complete and on time and within budget? What is the life of the project 1 year, 2 or 20. I would say the way this industry is going 3 to 5 years is lucky.
In "compromise mode", I suggest:
- that all code should be written, as far as possible, to allow the hookup of an unit testing framework. This is so that tests can be applied when desired without impact to the system.
- that the critical sections of the application be identified and tests written only for them.
- that time should be spent how to properly organise tests so that they can be easily maintained.
|
|
|
|

|
If the customer knew what they would save by requiring the developers to write unit tests, I think they would be willing to pay. I don't know of a customer that has enjoyed dealing with bugs and problems. I have been on some projects where the bugs were so bad that they almost cancelled the project. Unit tests are kind of like insurance. Without unit tests, I think it is a risky proposition to develop any kind of software application.
I have personally seen the benefits from writing good unit tests, and what is difficult to understand is that unit tests in most cases actually saved time. How does a developer test changes that are down in the core of the application? Are they really going to make sure that a single change (that may affect many parts of the app) are tested without a good unit test? We both know the answer to that question.
Last but not least, unit tests are no gaurantee that the software is going to work well, but it surely is better than the other alternatives we have that are not cutting it.
Something worth considering.
Kent
|
|
|
|

|
"Testing is great in theory"?
I'm sorry, but I think you're taking a very narrow and short-term view of software development.
Testing (of which unit-testing is one facet) is something that is crucial to any software project and the more complex the project, the more complex and thorough the testing needs to be. Customers *may* only look at cosmetics as you say but they'll always complain if it doesn't work because of a bug "under the hood" that wasn't picked up because of a lack of unit-testing.
A good testing strategy (including unit testing) is especially important if you're talking about developing software that will be maintained by many developers and released according to a quarterly release-schedule to several customers. Then testing is for YOUR benefit. Yes, stepping through code is good and should be performed by the developer *during* development, but writing a good unit test harness protects your code for the future. Repeatedly stepping through thousands of lines of code every time a module changes is far too expensive an activity.
Imagine what it would be like if a developer adds code to the module you wrote 9 months ago and the bug it causes in your code (because the then-correct assumptions you made aren't applicable now) isn't found until 3 months later by a customer. Still think you or someone else can find what's wrong in the 30k lines of code you wrote last year? Probably not without a lot of effort, time and expense.
This is when unit testing comes into its own - the developer adding the bug would have run the unit test which would have shown him or her that they've caused a regression in the module and shouldn't release the code they've just added. As someone else has pointed out, testing is an insurance policy for the longer-term.
As to your comment about having to maintain test harnesses as code is added and removed - yes I agree its a pain, but that's life and a price that simply has to be accepted if you want to write reliable, maintainable software that your customers are happy with and continue to be happy with. Ultimately, they're the ones who keep you in employment.
So in response to your question of who pays? You do. You're investing in your software's future after all. If you can get a contract that also pays for testing time, then count yourself ahead in the game.
Kev
|
|
|
|

|
I think we're missing the point here. The article isn't about why we need to conduct unit test. The article isn't about why customer should pay for unit test. The article isn't about why we should allocate adequate resource to quality assurance. These are business issues: If you plan too aggressively, the risk of overrunning the budget will, inherently, be higher. When you overrun your budget, the first place to cut-cost, naturally, is quality assurance and documentation.
What Marc contributed is a set of test patterns which provides us the necessary foundation/mental framework to help eliminate blind spots in executing unit test and development of test plans.
Norman Fung
|
|
|
|

|
The cost of testing should be in your initial estimate for the project. If the customer shows concern about the cost of testing (either money or time), you, as a developer/engineer, must show them the benefits that come from unit testing.
Take for instance the Pharmaceutical industry. Could you imagine what would happen if the FDA did not enforce rigorous testing on new and existing drugs? And who do you think pays for that testing?
|
|
|
|

|
I think most of the points about negatives against unit testing are made by those who have never done a project in this way.
Unit testing saves time, creates higher quality code and ensures that the code delivered is as close to the customers requirements as possible (not more not less). It answers the question of "are you finsished?" which is difficult without test cases and it means you can refactor/redisign/expand/fix a system so simply because you can test the behavoiur of the code.
As for developer productivity ask anyone who does unit testing correctly how much time they spend in the debugger - it will be close to never.
To the comment that unit testing requires upfront design this I believe is incorrect. Unit testing requires upfront tests - this is one of the biggest benifits of unit testing - you write code to pass tests and then you can refactor to design. You don't design code, write code to the design and then write tests to the code (which is, if one thinks about it - the completely wrong way round.)
For example TDD says: customer wants a search engine, they/we write up test lists and test data such as "Si" should find "Simon" and "Simone" but not "Jessica". Then the programmers write test fixtures to test against those requirements. The design is one which best meets those customer requirements.
Also, testing the GUI is not a massive issue. The GUI should be an extremely thin layer ontop of the code. You test the code and you've tested 99.9% of your program - the GUI is just .1%. Of course you still have to test the GUI but you aren't testing your entire application - you are mostly testing that the GUI layers calls your system correctly.
|
|
|
|

|
the urls for the 'Previous articles in the series' are incorrect, they should be .asp not .html.
another great article though
|
|
|
|

|
netclectic wrote:
the urls for the 'Previous articles in the series' are incorrect, they should be .asp not .html.
Fixed!
Thanks for pointing that out.
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|

|
Mark,
Great article. I always enjoy reading your articles.
The link at the top for "Fixture Setup/Teardown, Test Repetition, And Performance Tests" looks like it should be '...\..autp4.asp' rather than the '...\..aut4.asp' (or something similar, I am going on memory here). The link you have for it further on in the article is correct.
I'll reiterate the question that Nitron had: How do you find time? However you do it, keep up the good work!
Mike
|
|
|
|

|
Nice article! I liked your introduction on NUnit testing. You really got to the point.
I would to propose another pattern: Interface Test Pattern which would be a "higher level" pattern (a pattern using other patterns) that could test all the classes that implement an interface.
What I'm thinking of is , for example, writting a test fixture for IEnumerable and then automatically test all classes implenting this interface.
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|

|
Jonathan de Halleux wrote:
I would to propose another pattern: Interface Test Pattern which would be a "higher level" pattern (a pattern using other patterns) that could test all the classes that implement an interface.
Excellent idea!
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|

|
Ok, here I go with my ideas on the implementation of the InterfaceTest Pattern:
We will need a new TestFixture type that is intends to test interfaces implementation. Here are some important points (and new attributes):
- [InterfaceTestFixtureAttribute]: The objective is to design a way to create a single TextFixture for an interface and apply it to every class that implements the interface. This attribute denotes a testfixture class that tests interfaces.
- [InstanceProviderAttribute] The tester should be able to provide "interface instance providers" that will create new instance, manipulate it and return it to the test class. For example, if you want to test IEnumerableArrayList, you may first want to create a ArrayList, fill it with some elements and then apply the tests on the interface. Testing an empty ArrayList is pretty much useless.
- [InterfaceTest]: A problem with the above is that we need to use the class provided before the provider produces. A possible solution is to use a base class InterfaceTest that defines a public method Current:
public Object Current{get;set;}
This method can then be used at compile time to get a grip on the interface instance (see example below).
Let's see a bit of code that illustrates all that:
First of all, the provider class, which does not provide a particular interface, but is a provider for a class. Therefore one provider can be used to test all the interfaces that the class implements.
[InstanceProvider(typeof(MyClass))]
public class MyClassProvider
{
[CreateInstance]
public MyClass Instance {get...}
}
Note that this provider could be reused in other
interface test if the MyClass would implement
multiple interfaces.
Then, the InterfaceTest base class:
public class InterfaceTest
{
public Object Current {get;}
}
Ok, now the interface test class:
[InterfaceTestFixture(typeof(IMyInterface))]
public MyInterfaceTest : IInterfaceTest
{
[Test]
public void Test()
{
IMyInterface if = (IMyInterface)Current;
}
}
So what would NUnit do to get things working (pseudo-code)
providers = Create a type -> provider map;
foreach( interfaceTest in the test assembly)
{
foreach( class that implement the testedInterface)
{
if (!providers.Contains(class))
continue;
interfaceTest t = new interfaceTest();
t.Current = providers[class].Instance;
...
}
}
Comments ?
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|
|

|
Nifty idea. The only limitation I see off-hand is in the case where the interface doesn't specify the form the output takes. EG: IEnumerable. It simply specifies that an Enumerator can be had -- it doesn't specify what order, etc, to expect. The compiler will ensure that IEnumerable is implemented, which I think is about as far as it could be taken.
It would be trivial to extend this to testing subclasses of a given base class. Same limitation regarding overridden members, but I would somewhat expect that specifications are more likely to exist for classes than interfaces.
|
|
|
|

|
Keith Farmer wrote:
Nifty idea. The only limitation I see off-hand is in the case where the interface doesn't specify the form the output takes. EG: IEnumerable. It simply specifies that an Enumerator can be had -- it doesn't specify what order, etc, to expect. The compiler will ensure that IEnumerable is implemented, which I think is about as far as it could be taken.
Well ensuring that GetEnumerator() actually returns a non null enumerator automatically is already a (useless) test.
Ok, IEnumerable is not a good example, but take IEnumerator. There is quite a number of tests that you could be automated, no matter what object type is iterated:
- Reset should reset the enumerator,;
- Current should fail if MoveNext was not called,
- MoveNext should fail if it is called after the last element, etc...
When you are implementing custom enumerator, this kind of test should be automated so you know your custom enumerator class has the expected behavior.
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|

|
Right.. In that instance, the behavior is part of the interface specification.
|
|
|
|

|
I was pondering something similar the other day. I brought up a WebControl in the VS designer and the whole think bombed out with a stack overflow exception. The source of the problem wasn't immediately obvious, and though a more through unit test would have found it the way I actually located it was to write a unit test that tested all the System.Web.UI.Controls in the assembly for basic 'control-ness' - ie that all their properties could be succesfully read straight after construction. There I found my problem (and incidentally a few others).
So the concept of interface testing applies to any 'interface', rather than just those with a capital I - ie any derived class always inherits some functionality from the base class that should also be 'regression' tested when the derived class is tested. This seems to suggest three things:
- Unit tests need to be distributed along with any class intended for derivation (or even just any non-sealed class)
- Unit testing frameworks need to have a mechanism for discovering unit tests that apply to base classes, and applying them to the derived class being tested
- 'Reference' / library tests for common class types should be more widely available.
Do we have a generally agreed on library for .net unit tests yet?
|
|
|
|

|
piers7 wrote:
a unit test that tested all the System.Web.UI.Controls in the assembly for basic 'control-ness' - ie that all their properties could be succesfully read straight after construction.
Hi, I have implemented a similar concept in my Unit library (GUnit) which tests types. However, it is different from yours because it asks the user to provide "initialize" instances of the type:
[TypeFixture(typeof(System.Web.UI.Control))]
public class ControlTest
{
[Provider(typeof(MyControl)]
public MyControl ProvideMyControl()
{
...
}
[Test]
public void SomeTest(System.Web.UI.Control ctrl)
{
...
}
}
Of course, we could further imporve this by letting the framework load entire namespaces...
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|

|
piers7 wrote:
Do we have a generally agreed on library for .net unit tests yet?
lots of folks are using, and nearly all extensions flocking to, NUnit...works great for me....
|
|
|
|

|
pholser wrote:
lots of folks are using, and nearly all extensions flocking to, NUnit...works great for me....
hehe. Every read Jonathan Livingston Seagull?
Marc
Microsoft MVP, Visual C#
|
|
|
|

|
Marc, this Jonathan Livingston Seagull story has a lot of "historical" conotation with me. In fact, my folks named me after this movie/book... but somehow my father swithched bird and started to call me "pelican" which later on became "peli", This is my "official" name now.
NUnit is in fact the dominant and most used unit test framework, (although csUnit is trying to get a grip on this too but I don't really the point, thought they do not bring anything new into the game).
Anyway, after sending a few message on the NUnit forums, the answers were really like: "our solution is the best, don't bother with inovative ideas". Fact is they are stuck in their minimalist design! Am-I the only one feeling Unit Testing needs "a kick in the butt". I mean, we are in the era of RAD, so logically you would hope to get tests generated automatically or do some more intelligent testing that what is proposed in NUnit.
NUnit has opened the eyes of many people to the power of Reflection and meta data but I'm sure there is much work to do here. For example, combining IL exploration, executaion graph, and CodeDom generation, a unit test framework should be able to generate "empty" test classes whith one method for each execution path. Therefore, the tester knows how much tests he has to write...
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|

|
Jonathan de Halleux wrote:
Am-I the only one feeling Unit Testing needs "a kick in the butt". I mean, we are in the era of RAD, so logically you would hope to get tests generated automatically or do some more intelligent testing that what is proposed in NUnit.
I totally agree. When I first looked at NUnit, I laughed my head off--it was like, come on, this is *all* that it does? And there's a community of people oohing and aahing over it? Unbelievable. And even worse, there was no semblence of bringing some formal engineering practices to unit testing. It reminded me of the days when us 15 year old kids would get together and yack about the latest cool technology without a clue as to what we were really talking about. But since NUnit has its roots in Java, I don't really expect much more *cough* intelligence out of the community.
(yes, I am biased. I'm trying not to be, but hey, if there's a platform, I'll stand on it until I'm shoved off of it!)
Jonathan de Halleux wrote:
NUnit has opened the eyes of many people to the power of Reflection and meta data but I'm sure there is much work to do here. For example, combining IL exploration, executaion graph, and CodeDom generation, a unit test framework should be able to generate "empty" test classes whith one method for each execution path. Therefore, the tester knows how much tests he has to write...
Absolutely. We're progressing in that direction with VTS. There's a few things on the todo list that are simple and are higher priority (like running unit tests automatically from the command line and unloading/reloading assemblies), but then it's on to forward engineering and things of that nature. Eduard on the AUT site has been making major contributions to VTS.
Unfortunately, I've been so swamped that I can't do much right now myself.
Marc
Microsoft MVP, Visual C#
|
|
|
|

|
No sorry, I meant a library for the *tests*, not the framework for running them.
Not (obviously) a library full of people's highly-specific unit tests, but the generic ones: reference test harnesses for classes inheriting from 'wellknown' bases like Control (Web / Windows) and Component for example.
(Put it this way, if you were writing a device driver, would you write your test harness from scratch, or use a standard one, and write specific tests for your specific functionality)
Now admittedly each test implementation has a degree of framework-specificity about it, but the underlying test code is normally fairly portable.
My original point was that as I started writing my generic System.Web.UI.Control test it occurred to me that a) someone must have written this before and b) if not I should probably post it somewhere
|
|
|
|

|
piers7 wrote:
My original point was that as I started writing my generic System.Web.UI.Control test it occurred to me that a) someone must have written this before and b) if not I should probably post it somewhere
a) I don't know any implementation.
b) GUnit (sorry about lamming with this) is built such that you can create your own fixture. Therefore, we can think about a fixture that creates a control, try to call each property and do that for all the properties. The framework can take care of separating each "property" call into 1 separate test. Is that what you are looking for ?
Jonathan de Halleux.
www.dotnetwiki.org
|
|
|
|

|
http://www.placebosoft.com/abstract-test.html
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
An Introduction To The Concept Of Unit Test Patterns
| Type | Article |
| Licence | |
| First Posted | 4 Jan 2004 |
| Views | 523,645 |
| Bookmarked | 340 times |
|
|