rickardnilsson.net is a weblog and the online home of web developer and father of three, Rickard Nilsson... More
Rickard blogs about creating software solutions using ASP.NET and agile practices.
This blog post introduces CSRepl, the C# REPL and interactive interpreter which I have founded on BitBucket. REPL stands for Read-eval-print loop and is a simple, interactive computer programming environment. It can be used to evaluate C# expressions and statements on the flight as well as creating types (classes, stucts, enums).
CSRepl can conveniently be used to quickly explore .NET Framework classes and APIs as well as third party assemblies.
Download
Download installer | Wiki | Source | Report an Issue
CSRepl is implemented as a windows console application and to use it when installed, you simply start it with the csrepl command from the command line:
C:\Program Files (x86)\CSRepl\>csrepl
CSRepl 1.0 Interactive build 1.0.4383.22797
Copyright (c) trycsharp.org. All Rights Reserved.
For help type Help
>
Support includes, but does not stop at:
Literal expressions:
> 1 + 2
3
> 2 * 4
8
> "hello, world"
"hello, world"
Semicolon is optional:
> 1 + 2;
Sequence of statements:
> var x = 1
> x
1
> x = 2
2
Collections:
> new[] {1,2,3}
[1,2,3]
> var list = new List<int> {1,2,3}
> list
> var map = new Dictionary<int, string> {{1,"foo"},{2,"bar"}}
> map
[[1, "foo"],[2, "bar"]]
Method declarations:
> int Foo() { return 1; }
> Foo()
Type declarations:
> class Foo { public string Bar() { return "Bar"; } }
> var foo = new Foo()
> foo.Bar()
"Bar"
Multi line statements:
> class Foo
> {
> public int AddOne(int v)
> return v + 1;
> }
> foo.AddOne(1)
Using statements:
> new ArrayList {1}
The type or namespace name 'ArrayList' could not be found
> using System.Collections
[1]
Formatting of complex types:
> class Foo { public string Bar { get; set; } }
> var foo = new Foo { Bar = "Hello" }
> foo
Foo { Bar = "Hello" }
> var anonymous = new { X = 1, Y = "foo" }
> anonymous
{ X = 1, Y = foo }
> var xml = new XmlDocument();
> xml.LoadXml("<foo bar=\"baz\" />")
> xml
<foo bar="baz" />
Load external assemlies:
> LoadAssembly("ICSharpCode.SharpZipLib.dll")
> using ICSharpCode.SharpZipLib.Zip
> new FastZip()
FastZip { CreateEmptyDirectories = False, Password = null,
NameTransform = ZipNameTransform { TrimPrefix = null },
EntryFactory = ZipEntryFactory {
Setting = LastWriteTime, FixedDateTime = 2012-01-01 12:36:13,
GetAttributes = -1, SetAttributes = 0, IsUnicodeText = False },
UseZip64 = Dynamic, RestoreDateTimeOnExtract = False,
RestoreAttributesOnExtract = False }
After graduation I started out on my professional career as developer on the .NET stack. As I was new to the platform and tools I began searching for means to educate myself and continue to stay up to date with everything that was going on in the industry.
I found that listening to audio talk shows, or “podcasts”, was a great way to get an even flow of new information about the platform, industry and the .NET community. The podcasts quickly introduced me to a whole new world of MVPs, regional directors, .NET user groups, events, and conferences, new technology, as well as how it is to work in the business.
My advice to you, professional or student, novice or experienced, who is interested in building software with Microsoft tooling and products, follow one or more of these channels because for me, they really boosted my career and has been a cheap way for me to get ahead. I use the time on the commute every day to stay on top of things.
The .NET podcasts I have followed since the beginning and still follow every week are:
Subscribe · iTunes · Zune · Facebook page
Favorite shows:
642. Bruce Lawson and Remy Sharp on HTML 5 346. Future of .NET Panel at DevTeach Toronto 240. The ORM Smackdown!
Subscribe · iTunes
256. JavaScript and jQuery: Moving beyond Alert() 72. Be a Better Developer in Six Months 31. Test Driven
A while ago Manning Publications contacted me through this blog asking for my thoughts on a book that was about to get published. The title of the book was “Continuous Integration in .NET”. Obviously I was honored and this is my review.
I’ve been a Continuous Integration practitioner and evangelist for about a year and it’s been a fun ride. I’ve implemented the practice in my own team as well as helped other teams getting started with the process. I’ve also held a talk at work before 20+ developers about Continuous Integration, written blog posts, and answered questions on Stack overflow.
Are you a .NET developer who finds yourself in projects where releasing software is painful and takes forever? Then Continuous Integration in .NET is the book for you. I’ve been there over and over and thus started researching Continuous Integration tools for .NET about a year ago and found many of which are covered in great detail in the book by Marcin Kawalerowicz and Craig Berntson. The authors are both developers, bloggers, and have vast knowledge and experience with Continuous Integration.
The book is extremely rich when it comes to tools and in under three hundred pages these are some of the tools that are covered; Version control tools like SVN and TFS, unit testing and mocking tools like NUnit and Rhino Mocks, automation tools like NAnt and MSBuild, CI servers like Team City and TFS 2010, UI testing tools, acceptance testing tools, code analysis tools, document generation tools, deployment and delivery tools, and database automation tools. Flavor samples of all the tools you need to automate anything you can think of, and beyond.
In my experience starting with version control, a CI server and Unit testing goes a long way when you’re first starting out on the journey towards Continuous Integration. This is also the message [Kawalerowicz and Berntson] sends throughout the book. However, there are quite a bit of content for experienced CI teams as well, e.g. how to take the process even further with automated deployment, database rollouts or how to deal with speed and scalability issues in your build.
In my mind Continuous Integration is so much more than just the tooling and process automation, it is a complete development practice that dictates some of the team’s behavior. For instance, to get the rapid and repeated feedback that we strive after all team members need to commit working and tested source code at least daily.
I was a bit disappointed that the book didn’t cover any of this aspect. In the early chapters the CI concept is redefined by the authors for the scope of the book to exclude the development practice parts.
Continuous Integration in .NET is a very good and well-worked book and I can recommend it to anyone wanting to get started with CI in .NET but don’t know how, as well as more experienced CI developers looking to extend and fine tune their process.
If you’re interested in the development practice side of CI I recommend you read Martin Fowler’s article as well as the ground breaking book Continuous Integration: Improving Software Quality and Reducing Risk by Paul Duvall.
In the following example I will show how easy it is to isolate your client code from ASP.NET code, using the Moles Isolation Framework, in order to test that your code performs as intended.
The example should not be seen as an encouragement to use bad design. On the contrary, I urge you to use Moles to get that ugly, old legacy code you’ve got, and put it under test such that you will have the freedom to rip it apart and improve it.
Now Moles will generate an assembly with mocks and stubs of the target assembly (System.Web) and add it to the test project. Your references should look like this:
Now you are ready to start writing tests. First we take a look at our sample application. It is a simple ASPX-page which calls Server.MapPath() in the Page_Load method:
public partial class ServerUsageExamplePage : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { //... Server.MapPath("...");
//... } }
In our unit test we want to be able to replace the call to Server.MapPath() such that
The following test method will fake the call to Server.MapPath() and assert that it was actually called by the method under test:
[TestMethod] [HostType("Moles")] public void MapPath_WhenCalledWithProperContext_ShouldInvokeServerMethod() { // Arrange var mapPathWasCalled = false; MHttpContext.CurrentGet = () => new MHttpContext { ServerGet = () => new MHttpServerUtility { MapPathString = path => { mapPathWasCalled = true; return string.Empty; } } };
// Act var page= new ServerUsageExamplePage(); page.Page_Load(this, EventArgs.Empty);
// Assert Assert.IsTrue(mapPathWasCalled); }
To accomplish this we need to understand what is going on. “Server” is an instance property on the System.Web.UI.Page class which eventually will invoke the HttpContext.Current.Server property. Thus, to fake the method call we need to fake several things:
Finally, to be able to execute the method under test (Page_Load), we need to change its accessibility from protected to public.
I've shown how easy it is to get started covering your ASP.NET codebehinds with unit tests utilizing Moles Isolation Framework. Please leave feedback and any questions you might have. Good luck testing!
Have you ever wanted to rename a namespace but you have too many classes in the namespace that it would be an infeasible hassle changing all of them individually. Even using a tool like ReSharper to refactor the namespaces class by class is a hassle. I'm gonna show how to rename a namespace for all of its classes in a couple of key strokes using ReSharper.
Update! Alternate context menu option to rename namespaces. Tested with ReSharper 5.1.
and you're done!
Please leave a comment if you found this useful.
* Visual Studio scheme
Proceeding with a solution there is no way of changing the implementation of the GregorianCalendar class to get the correct behavior so we have to go about this another way. One is to subclass the GregorianCalendar and override the GetWeekOfYear method. Another is to implement the GetWeekOfYear in a class totally separate from the .NET framework. I think that the first one is the way to go since the error that we're trying to correct is in the framework itself.
So, first we alter the help method in the test case to use our sub classed IsoCalendar (which we haven't written yet).
So, we are not in a compile state yet so lets do the simplest thing to get this running. I decided to subclass the GregorianCalendar class since what is wrong is the GetWeekOfYTear method of that class. I basically override that method like below.
We run the test a get a red bar. Fine, but now lets go ahead and implement the algorithm. However, this has been done over and over with varying elegantness. My favorite is the work of programmer and mathematician Julian Bucknall. His original implementation can be found at his blog. So, instead of returning -1 I call the GetIsoWeek method from Bucknall's implementation and take the modulus of 100 (since the result from the algorithm is of the form YYYYWW). We run the test and we get a green bar!
Now when we get a green bar there's just one more thing to add. The ISO 8601 week should only be returned when the parameters rule and firstDayOfWeek is set properly according to the documentation. In all other cases the GregorianCalendar implementation works just fine. We fix this with a guard clause at the top and we're done.
During this series we covered test coverage for the faulty implementation of weeks according to ISO 8601. We used Test-Driven Development to provide a fix using Julian Bucknall's really smart implementation. Next we should take a look at refactoring to design patterns.
According to the ISO standard, in the period 4 January - 28 December the week number is always the same as the Gregorian week and the same also apply for all Thursdays. Thus, the mentioned dates can be safely excluded in our test coverage. Though we still have an infinite number of dates to cover, we are getting there. Finally, we can limit our test coverage to a set of years that can be reasonable argued to appear in the application which we are implementing.
To simplify it the resulting dates are non Thursdays 1-3 January and 29-31 December every year from 2005 - 2015.
Using the calendar in Outlook I compile a matrix of the week numbers in the year interval. The dates that are grayed are Thursdays which should not be part of the test.
The matrix can be thought of as a set of { date, week number } pairs which can easily be implemented in code.
I create a test which iterates over the set and makes assertions that the correct week was generated by the calendar. It turns out however, that only eleven of the dates generate a wrong week number. I refactor the code to only include the weeks that are wrong. I get a red bar and I see another opportunity for refactoring, the previous two tests can be integrated with this test by just adding the date - week pair to the set. The following is the resulting test:
Now that we have a test that fails we can come up with a solution to get the test to pass.
Abstract So, now we make up another test. Looking at the calendar we see that new years eave 2001 should also belong to the first week of 2002 according to ISO 8601. We write the test much like the previous test and we get another red bar. Now its time to refactor. We need to remove the duplicated code in the two tests. First we start with extract method which results in the following method:
Now, we can refactor the tests using the new method like this:
The implementation of weeks according to ISO 8601 (used e.g. in Sweden) is faulty in .NET Framework. In particular the GregorianCalendar and CultureInfo classes are faulty when it comes to ISO 8601. So, how do we know that the implementation of ISO 8601 is faulty using TDD? We come up with a test that fails. By the ISO definition the first week is the week with the year's first Thursday in it. So, we know that e.g. 2003-12-31 is actually week number 01 of 2004 since it is a Wednesday and thus belongs to the first week. The following is a first attempt at a test: Now we get a red bar and we know that the implementation is flawed. However, this is only a single test. If we get a green bar, is the implementation correct? No, of cource not. We need to write more tests to be sure.