Showing posts with label software-development. Show all posts
Showing posts with label software-development. Show all posts

Thursday, September 22, 2011

Workflow on the 2-person Recordings project

Hi everyone. Today I'm going to share the workflow we use on our project. Mostly for reference, I'll come back in a year and see how things change. Hopefully we'll be on other projects by then.

So let's just see the process for fixing a bug and deploying the fix to production. That will go through the entire process.

Step 1: Observe the bug happening

The bug I'm talking about is the canned graphs problem. Certain types of graphs showed this result:

The Undesirable Result

Great. After confirming that it's a Real Bug and not just user error, I create a new ticket on our bug tracker, Unfuddle: 

The bug report: You can see it's "fixed," that's because this is a current screenshot. 


 Step 2: Reproduce and isolate the bug with tests

In general I try to trap every bug with a unit or integration test. This particular bug had a good 'integration' test case for it, but I also wrote a UI test with Selenium

You can see that I'm exciting about Selenium because I used the phrase "real live selenium ui test."

Step 3: Bug fix

The build jobs that run during merges
The actual bug fix in this case was trivial (see the post mentioned above). After making the fix, the changes are merged from my dev branch into the Test branch (our main 'stable' branch). This merge is picked up by the build server, which builds the project, runs the tests, packages it into a WAR file, and archives it.

Step 4: Deploying to production 

Jobs running for Production
Once the build is good, the next step would be more thorough manual testing to determine any tweaks, additions, etc. before we stop working on the feature. In this case though, we can just merge to our Production branch. 

Now the fix is ready to deploy, so we can run the "Production Deploy" job. This will upload our WAR file to the live server which tomcat will automatically redeploy. After running "Production Status" to confirm the website is still running, we can visit it to confirm it's working.


Well, that's pretty much it! The process is more exciting for new feature additions, but it's basically the same process. Check back in a year to see how the process changes....

Sunday, June 19, 2011

Writing and testing a 2007 MS Word Add-in using NUnit, Moq, and the MVP pattern

Hey everyone,

Today I want to show you an approach to writing a testable UI. To do this I'm going to write a 2007 Microsoft Word Add-in using Microsoft's Visual Studio Tools for Office. The goal is to write an application level add-in and test it using NUnit and Moq.

 I'm going to design it around the Model-View-Presenter pattern: We'll have two interfaces: An IView, which will be an Office ribbon and contain no logic. Then we'll  have an IPresenter, which will handle all of the "UI logic" such as taking actions based on user dialog results etc.

Our Presenter won't actually have any domain logic in it: we'll be delegating that to another class (I'll explain that in a minute). This means that when we test it, we'll be doing behavior testing instead of testing for object states. This also means we'll be using Moq to setup our Mock domain objects and verifying that calls are made to them.

Of course it's important to note that this kind of testing involves some coupling between your tests and the implementation of the class under test, but I think it's acceptable since the Presenter is behavior based.

So what kind of add-in will we be doing? Well at first I was going to be boring and use a very contrived example. But then I came up with a nice domain-specific idea.

I figured why not do something chemistry related? That's always fun. So we're going to make an addition to the Word ribbon that allows the user to enter either a chemical formula or an entire reaction equation. When the user clicks the "Action" button, the add-in will either render the equation as an image and insert it, or if the user enters a single compound it will insert the molar mass at the cursor position.

Here's the user interface:


Don't worry about the actual logic behind rendering and molar mass calculation. I've already taken care of that using my chemical database program I wrote last year. Now of course I think the code is crap, but it still works and that's the main thing.

So let's get started by defining our interfaces. Our IPresenter will only contain a single method: Action() which returns void and expects no parameters. Our Ribbon will implement IView. To start with, we'll give IView two properties: MolarMass and EquationText:


IView.cs:
namespace Chemistry.UI
{
    public interface IView
    {
        double MolarMass
        {
            set;
        }
        string EquationText
        {
            get; 
        }
    }
}
IPresenter.cs:
namespace Chemistry.UI
{
    public interface IPresenter
    {
        void Action(); 
    }
}

In our first iteration we'll simply assume that the user-entered text is a compound and we want to calculate the molar mass of it. Let's write a simple test that will confirm our IPresenter implementation makes a call to our domain object (an instance of IFormulaParser):

Presenter.cs:
namespace Chemistry.UI
{
    public class Presenter : IPresenter
    {
        public void Action()
        {
            throw new NotImplementedException();
        }
    }
}
IFormulaParser.cs:
namespace Chemistry.UI
{
    public interface IFormulaParser
    {
        double MolarMass(string compound); 
    }
}
And now our test file, PresenterTests.cs:

using NUnit.Framework;
using Moq;
using Chemistry.UI; 
namespace Tests
{
    public class PresenterTests
    {
        private IPresenter _presenter;
        private Mock<IFormulaParser> _formulaParser; 

        [SetUp] 
        public void SetUp()
        {
            _presenter = new Presenter();
            _formulaParser = new Mock<IFormulaParser>();            
        }

        [TestCase] 
        public void Action_UserEntersCompound_CallsMolarMassMethod()
        {
            _presenter.Action(); 
            _formulaParser.Verify(parser => parser.MolarMass("O2")); 
        }
    }
}

So in our test class we initialize a new Presenter object and a mock FormulaParser. For now we've set the IFormulaPresenter to return a value of 32 when MolarMass("O2") is called. In our test case, we make sure that our FormulaParser is called correctly. Of course the test fails since Presenter doesn't do anything. Let's change it so that it uses the text entered by the user instead our hard-coded value.

using NUnit.Framework;
using Moq;
using Chemistry.UI; 
namespace Tests
{
    public class PresenterTests
    {
        private IPresenter _presenter;
        private Mock<IFormulaParser> _formulaParser;
        private Mock<IView> _view; 

        [SetUp] 
        public void SetUp()
        {
            _presenter = new Presenter();
            _formulaParser = new Mock<IFormulaParser>();            
            _view = new Mock<IView>(); 
        }

        [TestCase("O2",32.0)] 
        [TestCase("H2", 2.0)]
        [TestCase("C6H6",78.0)]
        public void Action_UserEntersCompound_CallsMolarMassMethod(string compound, double molarMass)
        {
            _view.Setup(view => view.EquationText).Returns(compound);
            _formulaParser.Setup(parser => parser.MolarMass(compound)).Returns(molarMass);                 

            _presenter.Action(); 

            _formulaParser.Verify(parser => parser.MolarMass(compound)); 
        }
    }
}


Now we've done a couple things. First, we've created a new mock IView. We also changed our test to accept parameters and set up the view's EquationText property with the compound string. Finally, we check again to make sure the presenter calls the FormulaParser.MolarMass method. Now let's make the Presenter pass the test.

public class Presenter : IPresenter
{
 private IFormulaParser _formulaParser;
 private IView _view;

 public Presenter(IView view)
 {
  _view = view;
  _formulaParser = new FormulaParser(); 
 }

 public void Action()
 {
  _view.MolarMass = _formulaParser.MolarMass(_view.EquationText); 
 }
}

Alright, so now the Presenter is using the IView's equation text property, calculating the molar mass, and setting the IView's MolarMass property to the result. Let's also update the test cases to verify that View's MolarMass property is also set:

[SetUp] 
public void SetUp()
{
 _view = new Mock<IView>();
 _formulaParser = new Mock<IFormulaParser>();                  
 _presenter = new Presenter(_formulaParser.Object, _view.Object);                  
}

[TestCase("O2",32.0)] 
[TestCase("H2", 2.0)]
[TestCase("C6H6",78.0)]
public void Action_UserEntersCompound_CallsMolarMassMethod(string compound, double molarMass)
{
 _view.Setup(view => view.EquationText).Returns(compound);
 _formulaParser.Setup(parser => parser.MolarMass(compound)).Returns(molarMass);  
              
 _presenter.Action(); 

 _formulaParser.Verify(parser => parser.MolarMass(compound));
 _view.VerifySet(view => view.MolarMass = molarMass); 
}

At this point, our test passes. And at this point if we implement IView in our Ribbon object, everything should work. So let's proceed and implement rendering equations as well. Let's start by writing a test to make sure our rendering object is called. To do thish we need to add our IEquationRenderer interface, which has a reference to System.Drawing:

public interface IEquationRenderer
{
 Image RenderEquation(string equation); 
}

And modify the Presenter constructor:

public Presenter(IEquationRenderer equationRenderer, IFormulaParser formulaParser,  IView view)
{
 _view = view;
 _formulaParser = formulaParser;
 _equationRenderer = equationRenderer; 
}

Finally add our test case:

[TestCase("H2 + O2 ----> H2O")]
public void Action_UserEntersEquation_CallsEquationRenderer(string equation)
{                        
 _view.Setup(view => view.EquationText).Returns(equation);            
 _presenter.Action();
 _equationRenderer.Verify(renderer => renderer.RenderEquation(equation));
 _view.VerifySet(view => view.EquationImage = It.IsAny<Image>()); 
}

An important note here: I wasn't able to mock the Image interface that we're passing around, so we're verifying that the IView gets its EquationImage property set to "any" Image object instead of a dummy Image that we would pass around normally.

If we make this test pass by just adding a call to our EquationRenderer, we could also still be calling the molar mass calculation which we don't want. So let's add another test that ensures that when we parse an equation, we don't try a molar mass calculation:

[TestCase("H2 + O2 ----> H2O")]
public void Action_UserEntersEquation_DoesNotTryMolarMassCalculation(string equation)
{
 _view.Setup(view => view.EquationText).Returns(equation);
 _presenter.Action();
 _formulaParser.Verify(parser => parser.MolarMass(It.IsAny<string>()), Times.Never()); 
}

This test will fail because we need some conditional logic to differentiate compounds and equations. Let's do this by adding a method to IFormulaParser:

bool IsEquation(string text); 

Let's set this up in our equation tests to return true by adding this setup line to our two test cases:

_formulaParser.Setup(parser => parser.IsEquation(equation)).Returns(true); 

The actual implementation will just check for the presence of "---->," but that could always change. Now we can modify the Presenter to take this into account:

public void Action()
{
 if (_formulaParser.IsEquation(_view.EquationText))
 {
  _view.EquationImage = _equationRenderer.RenderEquation(_view.EquationText); 
 }
 else
 {
  _view.MolarMass = _formulaParser.MolarMass(_view.EquationText);
 }            
}

And now our tests pass. At this point, the rest of the work is implementation details. Here's an example of the final result:

The important thing to note with this approach is that we've created an extremely testable UI layer. Since all of the logic is in the Presenter class, we can test all aspects of the UI. This becomes even more exciting when your UI logic involves the user making decisions by answering prompts and responding to dialogs. You could for example wrap a call to MessageBox.Show in an IView DisplayMessage() method that returns a DialogResult. This would allow you to test the Presenter and just mock the IView.

Anyway, just for reference, the full source code of this add-in is on my website. Apologies in advance for the weird project structure, the Test project is under the "Tests" folder. The solution uses Visual Studio 2010.

Monday, April 18, 2011

Code coverage, Hibernate integration, and other fun things.

Hello everyone,

Lately our project has been progressing very nicely. My colleague had written a small program to parse raw data into an SQL-friendly form, so we are not restricted to test data anymore. This has the nice side-effect of boosting motivation because we are dealing with the Real Thing now.

My focus lately has been on adding a comments section to the web app. In our schema, we have a few different comment tables for different types objects. Luckily in the Java code we can just make all of them derive from a BasicCommentBean so we can be lazy. I've made the comments section as generic as possible and self-contained.

With this setup, you can reference comments.jsp and set the required attributes (a comment data source namely) and everything else is handled for Free by CommentController. We also perform server-side validation on the user input and sanitize it via the apache.commons.lang library to prevent malicious code execution on the client. Oh and we have some nice ajax and animation going on courtesy of jQuery...

Now that we're using real data, we've integrated Hibernate. Oddly enough, the process was surprisingly painless, but I wouldn't be care-free just yet... I don't have a ton of experience with Hibernate, but so far it's pretty straightforward once the mappings are working correctly.

One last think: I've been experimenting with code coverage via the EclEmma plugin for eclipse. It's nicely integrated and I've used it to see how much code coverage our unit tests are providing (63% ... looks like room to improve). Over the next few days/weeks/etc. I hope to use it more extensively to improve our tests and coverage of the important parts of the project.

Wednesday, March 30, 2011

Putting your old code to use in a new project

Hey everyone,

For the past few days I've been working on a chemical structure drawing tool, and even though I don't have that much time to work on it this week I've still been making progress. Now, I'm a really lazy programmer, so naturally any code from other projects that I can incorporate shall be incorporated. So it was a really tempting idea to borrow the structure rendering code I wrote for my chemical database program. (Aside: I wrote it last summer and I think the code is terrible ... how things change)

It was a nice setup at the time, there is a Renderer class which handles the actual drawing (via GDI), and a CompoundViewer class which updates the renderer, handles support for more than one compound, allows selection, deletion, etc., and more useful things. 

However, there are several problems that were keeping me from just dropping it in:
  • CompoundViewer uses different representations of structures than I'm using now (the old approach was comparatively sloppier) 
  • Chemical bonds store the index of the atoms they are bonded to instead of pointers (as they do now) 
  • A lot of methods in the old implementation of Compound are absent from the new implementation
 Still, it seems a shame to have to rewrite something that works well. Plus, the code has had numerous fixes for odd issues that I would probably overlook when rewriting. So instead of rewriting the rendering code, I kept it and scrapped the rest. The reasoning? CompoundViewer contains a lot of functionality that is heavily coupled to the old implementation of Compound, and refactoring it would probably be more trouble than it was worth.

To salvage the Renderer class, I added three new interfaces (ICompound, IBond, and IAtom), and the new versions of these classes implemented them. The required methods/properties that went into the interfaces came directly from what the Renderer class used. The good news is that this turned out to be very painless, and each interface only contains a few methods/properties. I was able to get a test up and running that rendered a simple compound correctly.

When I begin on the GUI side of this project, I won't have to rewrite the important code that actually draws the compounds. As a bonus, the Renderer class maintains compatibility with the old versions since they implement the interfaces already. It's like you win twice!

Sunday, March 27, 2011

Chemical structure drawing with C#/VB.NET and TDD

So a little fact about me: I picked up chemistry back in 2007 and I really enjoy the subject*. Naturally I like to apply software development to chemistry-related problems (see my chemical database for an example).

I figured "hey Chris, you haven't made your own structure drawing tool yet," and it would be a good fun learning experience. Right now I'm using a C# back-end for all of the logic and plan on using a VB .NET UI front-end just to pick up the language. Also, I've really been trying to get more out of TDD and practice it more. I've tried to stick to it and so far it's going pretty well, although there is room for improvement.

I also finally decided to pick up AnkhSVN, which provides integration of Subversion into Visual Studio. So far it's working pretty well.

Anyway, here's some of the things I hope to implement:
  • Basic editing: adding/deleting of atoms and bonds
  • Support for adding fragments at once instead of having to create them each time
  • Saving/loading of structures in some common formats
  • (possible) integration into my chemical database program since it currently relies on an external editor
We'll see how far that goes, hopefully I'll have some screenshots too. Unfortunately it will probably be slow progress since I'm being bombarded with assignments this week (chemistry professors here seem to like homework as opposed to projects, which CS professors and I prefer...)


*My favorite experiment was distilling liquid bromine from KBr/H2SO4/H2O2 solution ... good times. One of  my general chemistry professors even helped me improve the process

Wednesday, March 16, 2011

Hosted issue tracking with Eclipse integration

Alright.

Since the project we're working on is a good size, we've decided to go with an issue tracking solution instead of trying to remember everything. Since neither of us can guarantee uptime on a private server with an issue tracker (such as Bugzilla) installed, we resort to hosted solutions.

And since we're just starting out, working on a free project (for fun), and have limited funds, we would like a very low (== free) cost solution as well.

And finally, we've gotten into really making our IDE integrated. We have our source control plugin (MercurialEclipse), Ant (automated deployment), and it seems natural to have an integrated issue tracking solution as well. Luckily, Eclipse comes with Mylyn, which provides an interface for issue tracking inside Eclipse. So all we need is an issue tracker that:
  • Is free for 2 people
  • Is hosted
  • Has a Mylyn connector for Eclipse
We would also like it to integrate with Mercurial. But you can't have everything.

After looking around and almost giving up, the solution I found was Unfuddled.

Let's take a look at what they offer compared to our requirements
  • Free for 2 people? Yes, <= 2 people get the issue tracking for free
  • Hosted? Yes
  • Mylyn connector? Yes, and it's stable and has good documentation. 
  • (just for fun) Source control integration? Git and Subversion. So no Mercurial. But it's hard enough finding a solution that fits the first three!
So far I'm pretty excited about using it, it seems very useful and what we're after. But let's see if I think the same thing 3 months in the future... 

Saturday, March 5, 2011

Design issues: Keeping it simple and practical

On the project I'm collaborating on with a former classmate, we are really trying to make some good design decisions. Stuff like:
  • Code reuse
  • Decoupled design (ie. data separate from domain) 
  • Testability (programming to interfaces) 
At the same time, we want to keep the design simple and easy to follow. One of the things we were trying to solve was handling very dynamic queries in an elegant way. And we came up with a solution. And it was elegant. It had everything based on some common interfaces, used generics to handle them, and even reflection sprinkled in.

And then we got rid of it in favor of a simple, more practical solution. 

Actually, he proposed the simpler solution. His solution was based on his practical experience developing applications. Although our elegant method would have been pretty cool, it would be less maintainable and take longer. And remember that in the end, your users don't care about your elegant solutions. They just want your stuff to work.

Tuesday, February 22, 2011

Approaches to supplying software updates to your end-users

Let's say (hypothetical ... of course) that you have released a piece of software and users have downloaded it. Suddenly you find a bug that you immediately smash in the next revision. Unfortunately, this particular bug is pretty annoying for you (the developer) and you don't want your users getting rid of your software. How do you go about ensuring that they get an update? Here are some approaches I thought of:
  1. Hope the users navigate to your website every so often to check for updates
  2. Add an automatic update program to your application
  3. Have a "check for updates" option in your program
Unfortunately, options (2) and (3) require that you have done this before placing your application for download. Option (1) is a bad idea (at least according to my website traffic) because people don't come back to your home page very often (if at all). So what do we do?

The way I see it, we have to settle for a compromise. Implement option (1), but also go ahead and either do (2) or (3) for future releases of your application. That way anyone who downloads it from now on will have update capability. Depending on how much time you want to invest, you might go with a full blown automatic updater or just settle for a "check for updates" option.

How do you go about checking for updates? If your application tracks its version, you can compare its version number to an official version number on your website (stored in a text file perhaps) by requesting it from your application. Then if the versions dont match, you can inform the user and direct them to the update website.

Now the next step is to find time to actually implement those ideas...

Sunday, February 13, 2011

HTML Combiner -- a small utility for inserting HTML into multiple pages

No doubt if you've worked on websites before you've wanted to reuse common blocks of HTML code across multiple pages -- such as the link bar on the right of this page. Normally you could accomplish this through Server Side Includes (for pure HTML), iframes, or even Javascript. Now my web hosting plan doesn't support SSI, and after reading about the downsides of iframes I'm not very ecstatic about using them either. Finally, I can't see myself using Javascript just for a links bar -- if someone has it disabled then they can't navigate my site!

So, wanting an excuse to write some C# code, I wrote a small utility that allows you to reuse HTML code by inserting tags throughout your website. The program then inserts your block of code where those tags appear in a the pages you want. In fact, I've been using it across my website for the links bar and also some statistics tracking scripts. Here is a screenshot of the main screen

Hoping that someone else might get some use out of it, I've put it up for download on its own page and submitted it to several software download sites. I haven't distributed my own programs since 2007, so it was an interesting process. In fact, it reminded me of a nice fact:

Programming is easy. Releasing software is hard

I have a very simple utility, but I have to put up with quite a few issues:

  1. Making sure there are error handlers everywhere
  2. Setting up an installer (an adventure in itself
  3. Targeting a version of .NET that is widespread (I chose 2.0)
  4. Writing a help file
  5. Building the product website
  6. .... (more) ....
Actually it took me a good 6-7 hours to finish everything, and there are still alot of things I need to add. But it's up now, so I'll be able to add to it pretty easily.
That's all for today -- in my next post I'm going to talk about my recent experiences with adding integration testing and also my attempts at unit testing methods that are heavily dependent on FileStreams.