Many viewers of one or more of my screencast series, Summer of NHibernate or Autumn of Agile, have seen me make use of several utility and base class libraries that I have developed over the years. Some have expressed interest in using some of these libraries in their own work projects. Some have asked permission to do so (granted!). Still others have even de-compiled some of these and attempted to pass them off as their own work
Some have asked if the source for these libraries could be made available as open-source, either out of a curiosity as to how they work or as a precursor to the adoption of these libraries in their own work (e.g., if you can get your hands on the source, then using such libraries inherently carries less risk since you can bug-fix, maintain, and otherwise support yourselves were I to disappear from the world tomorrow or decide not to update these libraries when .NET 7.0 is released in 2015).
I am pleased to announce that I have decided to do exactly that: after some minor code-cleaning and additional commenting to improve the auto-generated API reference documentation, I’m happy to report that these libraries have now been released as a single open-source-software project I have dubbed Proteus.
From our good friends at Wikipedia (source of all knowledge in the Internets), the name Proteus connotes “first”, “primordial”, or “firstborn” as well as forming the root of the word protean carrying further connotations of “flexibility”, “versatility”, and “adaptability”. All of these adjectives describe aspects of what I was trying to accomplish with these libraries and so I have co-opted the name of the Greek god for this project (hopefully Zeus won’t strike me down for it).
Proteus.Utility.UnitTest
Providing a set of base classes from which to derive your unit test fixtures, this library ensures consistency of test categorization, offers many conventions that help effectively drive the use of the NDbUnit tool to support database state management during integration tests, and offers several convenience methods to further assist in unit-test-writing.
Proteus.Domain.Foundation
Containing a series of base classes to support persistence in Domain Model objects, this library offers a set of core classes and interfaces that simplify the definition of persistent entities as well as offering an implementation of a collection of Specification pattern base classes to simplify the coding of specification classes in your solutions.
Namespace Change
Part of preparing this code for release involved changing the namespace and assembly names from their prior root to the new Proteus namespaces and assembly names. Otherwise these libraries (at least in this initial release) are identical (API-compatible) to their prior unreleased counterparts in every way.
This means that to migrate to these new versions from the prior versions that were previously only available ‘unofficially’ in the code sample downloads that accompany some of my screencasts all one needs to do is to follow these steps:
- delete the prior binaries from your solutions (*.Common.Utility.UnitTest.dll and/or *.Domain.Foundation.dll)
- download the new binaries and reference them into your solution(s) as needed
- do a solution-wide search-and-replace to substitute the prior namespace instances with the new Proteus namespaces (e.g., using Proteus.UnitTest and using Proteus.Domain.Foundation)
- you’re done
ONE BREAKING CHANGE: Rhino.Mocks Dependency Eliminated
A source of continuing challenge for me with this codebase was the Proteus.Utility.UnitTest library’s dependency on the Rhino.Mocks.dll assembly. I (reluctantly) took this dependency from the beginning with this library so that the UnitTestBase class could provide an instance field of type Rhino.Mocks.MockRepository as a convenience for test-authors to avoid the need to constantly new-up an instance of the MockRepository class just to create mock objects for their tests.
For a time this approach worked just fine for my library. But then things got really messy for me when Ayende (cleverly) actually released two functionally-compatible but syntactically-incompatible instances of RhinoMocks 3.5. One was .NET 2.0-compatible and didn’t support lambda statements and the other supported .NET 3.5 and introduced a very succinct statement syntax heavily leveraging lambda expressions.
While this was great for users of RhinoMocks (myself included, of course), for the Proteus.Utility.UnitTest library it meant that I needed to compile two instances of this library as well, one for .NET 2.0 and another for .NET 3.5. Not the end of the world, but annoying all the same both for me as a library author and for users of the library to keep straight too. Begrudgingly, I did so however as I saw no other choice in the matter as like Ayende I also wanted to support .NET 2.0 scenarios with my library.
With the moving of the code to the Proteus.Utility.UnitTest library, I am hereby taking this opportunity to once and for all eliminate the dependency on RhinoMocks — not because I don’t like RhinoMocks (it continues to be my favorite .NET mock objects tool) but because the instance of the MockRepository class is just no longer needed for RhinoMocks. With the support Ayende has introduced for the so-called AAA (Arrange, Act, Assert) pattern with the framework, most if not all mock object creation can now be performed on the static MockRepository class without requiring an instance of the class to do the work for you. This has reduced (if not eliminated) the value of having an instance field in the test fixture base class that holds a MockRepository instance and so I have herewith factored it completely away for good.
The benefit of this to me (and to you!) is that there is once again just one version of the Proteus.Utility.UnitTest library regardless of your target .NET framework version. Hallelujah! Simplicity is achieved once again and order returns to the universe!
Hosted on Google Code
If you’re interested in the code, its now hosted on Google Code at http://code.google.com/p/proteusproject/.
If all you want are the updated binaries, you can find those on the downloads tab of the same Google Code site. Note that there are two downloads, one each for each of the libraries but both ZIP archive files contain the single entire API reference document (chm format) for both libraries (e.g. there are two libraries but only one common API reference document).
NDbUnit Version Integration
If you are using the Proteus.Utility.UnitTest library for its integrated support of the NDbUnit tooling, then you are advised that the binary of NDbUnit that is supported by the Proteus.Utility.UnitTest library is included in the download for this library from the above-referenced Google Code site. I cannot be responsible for attempts to integrate any other NDbUnit release with this code (which is why there is a NDbUnit.Core.dll included with this download)!
Since I am the primary active maintainer of the NDbUnit project, I think its safe to say that this collection of software libraries will mature pretty much in sync with each other but to avoid any confusion about what version of the NDbUnit library is supported by what version of the Proteus.Utility.UnitTest library, users are strongly encouraged to use the NDbUnit binary in the Proteus.Utility.UnitTest library archive download at all times just to be safe
Happy coding~!
Wow, Christmas came early this year.
Nice job Steve, just a few more actions like this and you’re the new Hanselman ;-). (I tried to come up with a good name for your new podcast, but the name ‘Bohlen’ seems quite resistant to that :-). Disclaimer: English is not my native language, so perhaps some other folks around here can come up with a catchy name)
While you’re waiting for Camtasia to render the next installment of AoA ;-), how about a post in which you enlighten us in how to use these Proteus libraries (the way you intended it) ? Yes, I am aware that you used it (in one way or another) in your excellent screencast series, but a ‘single stop’ post could/would be nice.
(While I think that screencasts are a great way to learn new stuff, I don’t think they make for very good reference material)
One more comment about AoA, and then I’ll shut up about it.
We (and I think I can speak for most people here) realize that you’re producing these screencasts on your own time, and that’s much appreciated.
That being said, if someone asks when the next installment is going to be posted, _maybe_ you should say something like ‘I’m working on the next installment and I’ll let you know when it’s done’, instead of ‘It’ll be online next weekend’.
One
Hi Steve,
where did you use Proteus? did you use in Autumn of Agile series?
it will be good if you have small screen cast shows how would you use (Proteus.Domain.Foundation) perhaps ?
thanks
Thanks so much, your contributions are much appreciated
Steve,
Thanks — once again — for all your hard work and your continuing contributions to the greater good!
Howard
Hi Steve,
I’ve been learning C# and .NET for about 6 months now and can honestly say your screencasts and code samples have been the best source of learning I’ve found out there. Many thanks.
Can I vote for a ‘Spring Of Patterns’ series if that’s not too cheeky?
Thanks once again.
Delordson
Awesome! Looking forward to diving into the code of these projects.
Hi Steve,
can u explain the purpose of the LastUpdatedBy, LastUpdatedDateTime and IsTransient and the more important how they actually work. I did not find any tests for these fields/props.
10x
@mynkow:
Sure. The intent had always been to dig into those aspects when I completed the Autumn of Agile screencast series, but that’s still delayed so I’ve no problem explaining the intent here…
LastUpdatedBy and LastUpdatedDataTime are properties that the base class provides for NHibernate event listeners to populate on Save/Update actions performed on the objects.
Although I didn’t get that far (yet!) in the screencasts, NHibernate provides a rich persistence eventing model that permits you to ‘step in’ at various points in the CRUD lifecycle and the intent was to wire up an event listeners that would populate these properties right before the object is committed to the database on either an INSERT (save) or UPDATE (update) operation. FWIW, the interface needed to be implemented is ISaveOrUpdateEventListener (not surprisingly!).
The intent if IsTransient is to solve the ‘problem’ of not wanting to expose the ID of the persistent object outside the domain entity (or more importantly, the ‘meaning’ of the ID property outside the domain entity). Rather than code outside the entity having to inspect the ID of the entity and compare it to some ‘known uninitialized value’ (e.g., ‘0’ if an int/long or ‘0000-0000-0000…etc’ in the case of a GUID), the IsTransient property permits the object itself to encapsulate its understanding of how *it* can know if it’s persistent or transient and simply report that fact back to the outside world as a boolean FACT. In this way, the code consuming the object (that might care if it’s persistent or transient) doesn’t have undue intimate knowledge of HOW to determine that fact but instead just asks the object the question and gets an answer in the form of the IsTransient property.
Does that all make sense…?
Yes, yes. 🙂 Now I understand this. I think that I will add and created, createdby fields too.
Q:Is it possible to use Proteus.Utility.UnitTest and load data without using datasets? Because I have postgre server and I have big problems connecting server explorer with that server.
Thanks Steve 🙂
@mynkow:
The database-related behavior of the Proteus library is tightly-dependent on NDbUnit which in turn is dependent on datasets as the persistence mechanism for the test data it loads/resets/etc.
A few questions:
1) what troubles (specifically) are you having with postgres + server explorer?
2) If you cannot conn to the DB using server explorer (to create the XSD for the dataset) have you tried using MyGeneration to generate the XSD for you (perhaps better luck at connecting to postgres from there)?
3) If datasets/XML weren’t to be the persistence mechanism for the test data to load/reset/etc., do you have any suggestions for any alternate file-based persistence mechanisms that might be used in their place? (obviously for the Proteus database facilities to have any value, they need to be able to load persisted data into the DB on command).
Thoughts –?
@mynkow:
Oh, and one more thing — as you can see from this issue on the NDbUnit site ( http://code.google.com/p/ndbunit/issues/detail?id=13 ) there is some issue with its OleDb infrastructure not working with other than SQL Server (yeah, its a screw-up to be sure) so even if you could get the dataset issue solved, you wouldn’t be able to use NDbUnit (or Proteus) with PostGreSQL until this was resolved (or until I — or someone else! — writes a shim for PostGre for it.
As with most OSS projects, patches are welcome when accompanied by requisite unit tests 🙂
-Steve B.
Thanks Steve. This is the problem with ServerExplorer: http://archives.postgresql.org/pgsql-novice/2005-09/msg00042.php
Well, I will go trough the nDbUnit’s code and If I can handle postgre then I will rename all 1000 rows and tables with small caps/letters 😀 But server Explorer is now running with small test table 🙂 I hope I get the code and write a patch 😉
It is me again 🙂
I have a question about the UpdatedDateTime and UpdatedBy. I implemented ISaveOrUpdateEventListener but I want to ask you whether we can do something global. So we can have only one implementation. The problem is that these properties are read only.
Greetings from Bulgaria 🙂
@mynkow:
Sorry I didn’t reply to this sooner — somehow I missed your comment in my rss reader. The intent was that you would use reflection in the event listener implementation to set the values of the underlying fields in the class for those read-only properties.
Yes, its got some (minor) overhead vs. setting the property directly, but IMO this is a better strategy than permitting these properties to be read-write on the domain entity.
Hope this response finds you in time and sorry for the delay~!
Thanks Steve. I did some tests last week with reflection and read/write properties. With the system that we are building reflection will slow the program too much. The results are that with reflection we are ten times slower with 50 000 records at a time. I changed the proteus with read/write properties and added createdDate and createdBy fields and I am happy with that.
And Yes, you are right that permitting the properties to be read only is good but I think it is better to speed up the system instead 😉
Thanks for the help, It was really helpful
Greetings from Bulgaria
@mynkow:
Well, that’s why it *is* open-source…feel free to change the behavior as much as you feel you need to for your own situation 🙂
Glad you got it working satisfactorily for you!
-Steve B.