• Scrum with Specialists or ESPs

    It can be quite a challenge to put on a sprint planning. There are many personalities, interests, goals, and expectations. In extremely deep n-tier architecture with an even deeper org chart you may find yourself the target of some seriously frustrated developers (or worse become a dead ScrumMaster) if you just treat a specialist or an external service provider (ESP) like a normal team member.  For those who don’t have the luxury of a top-down scrum implementation you may gain some benefit from some of these techniques I’ve learned along the way.

     

    • Know which user stories require outside work at least 2 sprints in advance and lock in the resource with their functional manager. It’s often hard to get people if they’re committed to other project teams.
    • Engage vendors and non-scrum teams 1 sprint in advance (or more). It’s going to be difficult for most companies or teams to accept your tall order and deliver within 30 days. Be ready to work with non-agile teams.
    • Have your team help set the definition of done for ESPs. Utilize your team to set the acceptance criteria and definition of done for your external work. They will be validating it.
    • Treat outside departments like ESPs if they won’t join the scrum process. As always, try to get people on the cross functional team, committed, when possible. When that fails use the steps above (1-3).
    • Quickly run through and decompose specialist work in the first 10-15minutes of the sprint planning and get their commitment to the sprint. Dba, Webservices, that wonky mainframe programmer who watches cartoons on his lunch break… these people work for 5-10 projects at a time. Don’t abuse them by making them sit through an 8 hour sprint planning for which they contribute 2 hours of work in the overall sprint.
    • Include ‘support’ hours from specialists. Face it… they are scattered in 8 different directions. You probably will need them to fix a bug or two found later in the sprint.
    • Do not bring a story into your sprint that has outside dependencies that aren’t “Done” yet. A team cannot commit to something that they aren’t a part of doing… so don’t force them to commit on the good faith of a vendor’s commitment.
    • Assign a point person on the team to be in charge of integrating specialist/vendor work and make sure they task it out. Integrating during the sprint with each new piece of completed vendor functionality is important, but make sure a team member is there to make it happen… they’re a pig and will make it happen.

    Full story

    Comments (0)

  • MVP on Android

    Model View Presenter in Android

    Model View Presenter in Android

     

    I’m meddling with android programming now and I’ve found MVP is a great way to decouple presentation to allow for unit testing so I wanted to immediately get that practice down. Here is what I picked up.

     

    First, let’s create a project. I name the project MvpExample, choose a target platform of 2.1 (that’s what my phone has). Package name is like a namespace. Activity from what I can tell is the first view that your app opens up to. I named my AskNameView because I plan on asking the user for their name and age and then displaying it on the screen.

     

     

    It asks me for a unit test project. I am on the fence whether I like unit tests in the same project or not but in this case I don’t know enough to argue with the wizard J

     

     

    Let’s go into the test project and create an AskNamePresenterTests code file to start working on as we do TDD.

     

     

     

    Make a new class inheriting from TestCase

     

     

     

    Now this may seem like commonsense to you java developers but it took me a while to figure out there is a naming convention here required to do a test. Every test method must start with ‘test’. Annoying in my opinion because that’s 4 more letters I could use for a well named test. Here’s my first ‘always pass’ test to make sure I understood JUnit.

     

    package com.jpeckham.examples.test;

     

    import junit.framework.TestCase;

     

    public class AskNamePresenterTests extends TestCase {

     

          public void testFirst() {

                Boolean expected = true, actual = true;

               

                assertEquals(expected, actual);          

          }

    }

     

    So we continue on now. Let’s create our first presenter test for real.

     

    I write the test first without any supporting code. It looks like this:

          public void testFirst() {

                TestingAskNameView view = new TestingAskNameView();

                AskNamePresenter presenter = new AskNamePresenter(view);

                           

                presenter.EnterNameAndAge("James",25);//hah 25 :)

               

                assertAreEqual("James is 25 years old",

                            view.getTextShownToUser());

          }

     

    I figure I’ll wait to learn mocks until another day so I’m hard coding a fake view to work with here. The view will show “James is 25 year old” on it.

     

    Of course none of this builds yet because the classes don’t exist anywhere.

     

    Let’s start by making our TestingAskNameView class. Go to create new class on the TEST project. I created a new ‘fakes’ package (sub namespace)

     

     

    Note: for you MVP gurus don’t worry that I haven’t inherited from anything yet or implemented a view because I haven’t created one yet.

     

    Now if you go back to the test file and hover over the declaration of our local variable for the testing view you can see a  ‘quick fix’ that asks to import our new package “fakes”. Go ahead and do that.

     

    All the code looks like this now in the tests:

    package com.jpeckham.examples.test;

     

    import com.jpeckham.examples.test.fakes.TestingAskNameView;

     

    import junit.framework.TestCase;

     

    public class AskNamePresenterTests extends TestCase {

     

          public void testFirst() {

                TestingAskNameView view = new TestingAskNameView();

                AskNamePresenter presenter = new AskNamePresenter(view);

                           

                presenter.EnterNameAndAge("James",25);//hah 25 :)

               

                assertAreEqual("James is 25 years old",

                            view.getTextShownToUser());

          }

    }

     

    K, now I’m going to hammer out the presenter. Here’s the presenter code. Note it needs an instance of the view as a member variable (or some people call field). (not sure what they call it in java… class variable?) . Note this one is going into the android project.

     

    I do a little boilerplate mvp code:

    package com.jpeckham.examples.presenters;

     

    public class AskNamePresenter {

          private IAskNameView _view;

          public AskNamePresenter(IAskNameView view){

                _view = view;

          }

    }

     

    Now I use the IDE to generate the IAskNameView interface (new sub package)

     

     

    I’ll move a little quicker now. Here’s the interface code:

    package com.jpeckham.examples.views;

     

    public interface IAskNameView {

          public void setDisplayedText(String text);

    }

     

    Now go over to the android activity class  (the concrete view)

    package com.jpeckham.examples;

     

    import com.jpeckham.examples.views.IAskNameView;

     

    import android.app.Activity;

    import android.os.Bundle;

     

    public class AskNameView extends Activity implements IAskNameView {

        /** Called when the activity is first created. */

        @Override

        public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.main);

        }

     

          @Override

          public void setDisplayedText(String text) {

                // TODO Auto-generated method stub

               

          }

    }

     

    A few things to click on and generate here. (Don’t wire up anything yet we have some changes to do here in a few… we’re still working on making the presenter work)

     

    Now implement the view in the fake (over in the test project)

    package com.jpeckham.examples.test.fakes;

     

    import com.jpeckham.examples.views.IAskNameView;

     

    public class TestingAskNameView implements IAskNameView {

          private String _displayedText;

         

          public String getTextShownToUser(){

                return _displayedText;

          }

          @Override

          public void setDisplayedText(String text) {

                _displayedText = text;       

          }

     

    }

     

    Ok let’s see how we’re doing in the test project again… looks like the Presenter package needs imported.

    package com.jpeckham.examples.test;

     

    import com.jpeckham.examples.presenters.AskNamePresenter;

    import com.jpeckham.examples.test.fakes.TestingAskNameView;

     

    import junit.framework.TestCase;

     

    public class AskNamePresenterTests extends TestCase {

     

          public void testFirst() {

                TestingAskNameView view = new TestingAskNameView();

                AskNamePresenter presenter = new AskNamePresenter(view);

                           

                presenter.EnterNameAndAge("James",25);//hah 25 :)

               

                assertAreEqual("James is 25 years old",

                            view.getTextShownToUser());

          }

    }

    Now we need the EnterNameAndAge method stubbed in.

    public class AskNamePresenter {

          private IAskNameView _view;

          public AskNamePresenter(IAskNameView view){

                _view = view;

          }

          public void EnterNameAndAge(String string, int age) {

                // TODO Auto-generated method stub

               

          }

    }

     

    And a java rookie mistake I had assertAreEqual… let’s change that

          public void testFirst() {

                TestingAskNameView view = new TestingAskNameView();

                AskNamePresenter presenter = new AskNamePresenter(view);

                           

                presenter.EnterNameAndAge("James",25);//hah 25 :)

               

                assertEquals("James is 25 years old",

                            view.getTextShownToUser());

          }

     

    Now we have a failing test. In TDD with MVP that means you’re about 90% done because all of the architecture, design, and mvp boilerplate stuff is what takes the most ‘work’.

     

     

     

    Alrighty, now let’s make it pass. (ignore the duplication we’ll refactor…)

          public void EnterNameAndAge(String string, int age) {

                _view.setDisplayedText("James is 25 years old");

          }

     

    Ahh that’s nice:

     

     

    Ok now refactor out the hard coded values (and I fixed the param name)

          public void EnterNameAndAge(String name, int age) {

                _view.setDisplayedText(String.format("%s is %d years old",name,age));

          }

     

     

    Ok now the ‘easy’ part … design a droid UI and wire up the event.

     

    Let’s do a linear layout like this in our \res\layout\main.xml:

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="vertical"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"

        >

    <TextView 

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text=""

        android:id="@+id/shown"

        />

    <TextView 

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Name:"

        />

    <EditText

          android:singleLine="True"

          android:layout_width="fill_parent"

        android:layout_height="40px"

        android:id="@+id/name"

        />

    <TextView 

        android:layout_width="fill_parent"

        android:layout_height="wrap_content"

        android:text="Age:"

        />

    <EditText

          android:singleLine="True"

          android:layout_width="fill_parent"

        android:layout_height="40px"

        android:id="@+id/age"

        />

    <Button

          android:layout_width="fill_parent"

          android:layout_height="wrap_content"

          android:text="Submit"

          android:onClick="submitClicked"

          />

    </LinearLayout>

     

     

    And then finally hook up everything in the concrete view like this:

    package com.jpeckham.examples;

     

    import com.jpeckham.examples.presenters.AskNamePresenter;

    import com.jpeckham.examples.views.IAskNameView;

     

    import android.app.Activity;

    import android.os.Bundle;

    import android.view.View;

    import android.widget.*;

     

    public class AskNameView extends Activity implements IAskNameView {

        /** Called when the activity is first created. */

          AskNamePresenter _presenter;

         

          public AskNameView(){

                _presenter = new AskNamePresenter(this);

          }

         

        @Override

        public void onCreate(Bundle savedInstanceState) {

            super.onCreate(savedInstanceState);

            setContentView(R.layout.main);

        }

     

          @Override

          public void setDisplayedText(String text) {

                getShownLabel().setText(text);

          }

         

          public void submitClicked(View widget)    {

                _presenter.EnterNameAndAge(getNameField().getText().toString(),

                            Integer.parseInt(getAgeField().getText().toString()));

          }

         

          private EditText getNameField()     {

                return (EditText) findViewById(R.id.name);

          }

          private EditText getAgeField(){

                return (EditText) findViewById(R.id.age);

          }

          private TextView getShownLabel(){

                return (TextView) findViewById(R.id.shown);

          }

    }

     

     

    Then when you run as droid app… you’re up and running (if you can figure out how to turn yours to English unlike me …)

     

     

     

     

     

     

     

     

    CLICK for source code

     

    disclaimer: i know nothing about packaging java stuff so don't flame me on how i zipped this or if it doesn't work when you unzip it.

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

    Full story

    Comments (10)

  • Compiling Mud OS on Ubuntu 10.10

    Getting mudos to work on Ubuntu 10.10

     

    First.

     

    Grab the MudOS code and unzip it into your folder of choice.

     

    Go into the source code folder and edit local_options to set your configuration of choice.

     

    My first error after typing ‘make’ was this:

     

    No rule to make target obj/malloc.o. needed by ‘driver’. Stop

     

    I just typed make again and it kept on going… interesting…

     

    Second error:

     

    Socket_efuns.c:1198: error: lvalue required as unary ‘&’ operand

     

    This one was a little more interesting… the code looks like this on line 1198:

     

    addr_in = &(local ? lpc_socks[fd].l_addr : lpc_socks[fd].r_addr);

     

    Well, I googled around… saw something about a bug with getting a reference… anyhow I’m not expert on C but I modified the code to this and got the error to go away. I think it’s legit:

     

    addr_in = local ? (&(lpc_socks[fd].l_addr)) : (&(lpc_socks[fd].r_addr));

     

    typed make again… and away I went.

     

    Then it got to the linker and I got this error:

     

    /usr/bin/ld: cannot find –lbsd

    collect2: ld returned 1 exit status

     

    after some googling around I found out that means that my ld command cannot find the bsd lib *.a file…

     

    after some looking around I found that there is some config for it (described a bit here http://www.eyrie.org/~eagle/notes/rpath.html)

     

    /etc/ld.so.conf to be precise.

     

    Well /etc/ld.so.conf said this:

     

    Include /etc/ld.so.conf.d/*.conf

     

    So I went in that folder and found a bunch of conf…

     

    One of them looked like this inside:

    /usr/lib/mesa

     

    Cool… and another:

    /usr/lib/i686-linux-gnu

    /usr/lib/i686-linux-gnu

     

    Cool… so I need to make one for me… call it bsd I guess. But where is bsd at… so I looked around on my  box and found this

     

    /usr/lib/libbsd-compat.a

                                                                                                     

    So I ran this command

     

    Sudo cp /usr/lib/libbsd-compat.a /usr/lib/libbsd.a

     

    And ran make again. Finished. Cool!

     

    And then I telnetted into my mud. Ah memories.

     

     

     

     

     

    jackpot

     

    EDIT: some news. I'm getting 'back' into LP Muds and i found out that people have moved over to FluffOS http://www.fluffos.myzen.co.uk/

    So i switched over to the latest version of FluffOS and built that. it seems to build and run fine for my version of the DarkeLIB.

    http://lpmuds.net/forum/index.php?topic=1172.0

    Full story

    Comments (0)

  • Put the People back into People & Interactions

    I have seen some people saying things like: "which position in my company does the Product owner role?" or "I think that business analysts should be product owners" or "I think a product manager is the product owner" or "A programmer is on the team but a marketing person is a chicken"

    Our QA analyst makes the right scrum master because Ken Schwaber said it in a video.

    Ok stop all this madness because:

    the "People" in "People and Interactions OVER Processes and Tools" means "The real people" not their abstract title and position in the company.

    That is frankly meaningless!

    yes

    Meaningless.

    Remember the whole Pig vs Chicken thing?

    Remember the whole self selection thing?

    have you ever described the roles of product owner, team member and scrum master to the collection of people who are going to be working on the project and let them decide?

    hmm... maybe you've been bad at understanding the whole self empowerment thing?

    or maybe they need a little push?

    But you know what... if Fred the Product Manager drags his feet at being the product owner then maybe he's the wrong person to do the role? Someone else willing to step up? Do they have the support to do it? will the be able to be decisive? Maybe your Tom the Project Manager is a better candidate because Tom knows how to build consensus or build authority.

    Anyhow, the point is stop trying to put people into boxes that they don't belong in.

    Talk, discuss, get people who will own their role in scrum. Don't just assume such and such title and then 'pin it on them'.

     

     

    Full story

    Comments (0)

  • The Emergent Method

    Like last post, i'm trolling the tech ed videos. i wasn't so lucky that i actually got to go this year, but i'm glad that other people got to. Not that they need to more than I but that i'm glad they did and brought back an energy level for some new ideas.

    I started watching Juval Lowy on 'The zen of architecture'
    Get Microsoft Silverlight
     ... now i am not a BDUF kind of guy. I'm more of an emergent design type of guy. So when he said spend a couple of weeks to look at 'all' of the use cases I laughed a little bit to myself. There is no such thing as 'all of the use cases'... i think it is the same type of assumption that the requirements are out there you just have to 'capture them'. Some would say there is no such thing as a requirement because everything is negotiable.

    Anyhow... here's what I took away:
    1. use very light weight diagrams that are simple to understand
    2. use the 'transaction script pattern' from Martin Fowler's Patterns of Enterprise Architecture
    3. make every object a service (when appropriate, at least at entry point to layer boundaries) because it promotes isolation and a bunch of other good stuff.
    4. Why layers are important and some guidelines/starting points
    Here's what I would expand on for us agilists...for sprint 1 or sprint 0 if you believe in it.
    1. Build from the front to the back: Client first, then manager to create the stubbed in use case to identify the data.
    2. Choose a couple of user stories that have the most reason for volatility. For example if you are writing an application that does debit card authorizations... what about paypal authorizations or credit card authorizations in the future? Each of those types of authorizations is a variant of the authorization engine.
    3. Include user stories that will have a variety of authorization and authentication at different layers.
    4. choose a story that goes all the way through the architecture. a bad choice would be a javascript animation. 
    5. the amount of time spent should be scaled back to 2-3 days. Obviously negotiable just don't let it turn into a full design phase. 
    Instead of diagramming every single use case i would just diagram the first couple of user stories that you think might have the potential to meet the above criteria. For example, I was writing an advertising campaign system and my first user story was one that calculated the rules on whether to show the customer an ad based on their number of logins. It was 1 rule out of many, it hit all the major architectural pieces (web, app, data tiers) and it gave the customer something they could look at right away and expand on.

    So do a couple of use cases until you find the right ones and give everyone a feel for the big picture. do the design together with everyone... not just alone as the architect. Get the knowledge transferred to the team. 

     Ok now throw away the diagrams. They'll only cause confusion later on. 

    As an example, i had a customer contact me and ask me a few questions about what our software did in a certain scenario... the business analyst said ok i think i have thata documentation (the PRD). I said "i'll go check the code". She came back with the document and explained what it said... i read the code and explained that she was wrong. She actually argued with me on it...
    This is code that was developed and had been in production for years now... i'm pretty sure the code is right and the documentation is wrong.

    Point is here... you can make all of these diagrams and communicate a good vision for your product but the only lasting documentation of the project should be the unit tests and the code itself. Everything else is just an intermediate work item and is waste. Keeping it around can often only lead to confusion and misinterpretation. 

    If you do have to keep it around for any regulatory reason, just be sure to go double check yourself against the real code.

    Anyhow enough harping on documentation (i clearly have issues with it being misused).

    Frankly my rant on compliance and audits: I don't see why an intermediate piece of documentation needs to be kept around since code itself is a document... but that's another fight for another day. I would argue that the code is just as easy to read as the cryptic jargon they put in PRDs and it's WAY less ambiguous. in fact, it's never ambiguous, it does exactly what it says it does.

    Full story

    Comments (0)

  • Top 10 mistakes in unit testing

    Finally got around to watching this presentation.

    http://www.msteched.com/2010/NorthAmerica/DPR204

    Thanks Shawn! it was good stuff.

    Like Ben Day, i also program that way... it's very tough to try to program that way in a legacy program though. Which, i think every one of our programs is 'legacy' by the Michael Feathers definition. "code without tests"

    I would add legacy code to me it is

    "code without automated unit tests that give me rapid feedback."

    I will further clarify:

    "Legacy" is code that can not be tested and verified within 5minutes that all previous components still work in the same manner after my changes.

    I say that because a unit test can be interpreted in many ways... but you cannot misinterpet the ability to fully regression test your code and detect breaking changes within 5 minutes.

    and 5 minutes is a bit arbitrary... but the number is to mean "the maximum amount of time that the team will tolerate to run the test suite after every reasonable change"

    and by reasonable i mean... if you write some new functionality that completes a goal then run the regression suite. If you're just writing a component class/method then just run the test harness for that functionality (runs very quickly).

     

    So i feel like i'm rambling a bit but i've been really trying to stick to TDD in my code. I haven't really been able to achieve the structure that i would like... or the organization... i'm still struggling with finding the right folder locations and assembly organization.

    That being said things are moving along nicely towards TDD bliss.

    Next step is probably to figure out a IoC container... we already can use unity so i'll probably choose that out of laziness. I really love NInject the most though. Maybe once we're solidly on .net 3.5 i can use it.

    One thing that i've also struggled with is dependencies... we have a 3 tiered application and each tier is impossible to contain in a unit test. So i generally have MVP with a service dependency, logging dependency(yea i know i should use AOP), configuration dependency, and view dependency injected into the presenter. It starts to get pretty hairy!!!

     

    public class MyExamplePresenter

    {

        MyExamplePresenter(IExampleView view, IExampleConfigurationRepository config, IExampleBusinessLogicService service, IExampleBusinessLogicService2 service2)

        {

     

    Paraphrased of course... but sometimes the param list gets a bit long. maybe it's time to make a facade pattern interface for the BLL services? :)

     

    TBD!

     

     

     

     

    Full story

    Comments (0)

  • Back From Training Syndrome

    Lately I've had some luck capitalizing on people's energy after having some training. I think it was good that they've all been going to training and events around the same time frame because it's easier to push a boulder up hill with 5 people than only 1.

    If you're pressing for agile practices or trying to encourage a shift in thinking PLEASE try this advice:

    1. get everyone to agree on at least a similiar type of training. TDD or Scrum for example
    2. if possible send everyone at the same time so they all have the same frame of reference and they can all push together
    3. when they get back encourage them to try what they've learned and pick specific places to use it
    4. help remove any roadblocks to their experiments
      1. remove work if necessary until a steady pace or the new practices take hold
      2. block interruptions to their learning process to let them solidify their new skills at work

    Training is good if you can capitalize on the result of it otherwise people will move on to somewhere that they can use those skills. Don't become that company that trains people for other companies.

     

    Full story

    Comments (0)

  • Is Ninject 2 Stealthy

    Based on this documentation for Ninject , they claim to be stealthy!

     

    Stating:

    Ninject will not invade your code. You can easily isolate the dependency on Ninject to a single assembly in your project.”

     

    Well, at first I was skeptical and just could not figure it out. So I put on my scientist hat for a little while in an attempt to prove them right!

     

    Here’s what my test bed looked like… a pretty standard project configuration with multiple DLLs

     

      

     

     

    1. A console application. My driver program.
    2. A contracts DLL. My abstracts and interfaces that are known to the driver program.
    3. A service locator DLL. My services and Factories that will provide my driver program and class libraries everything they need.
    4. My first class library dll. This is where I would usually put some type of layered architecture or group of assemblies for a new release.
    5. My second class library dll. This is the same as above but separate from the previous one. 

     

       Now here are the references:  

     

    1, 4, and 5 reference 2 and 3. (and every dll you ever make after this would reference 2 and 3)

    3 references 4 and 5 (and any new dlls you ever make) 

     

    Here’s the layout of where all the type definitions are so you can visualize it:

     

     

     

    Here’s the driver program code. The test bed for this little experiment: 

    using System;

    using IsolatingTheNinja.Contracts;

    using IsolatingTheNinja.Services;

     

    namespace IsolatingTheNinja

    {

        class Program 

        {

            static void Main(string[] args)

            {

                ILibrary1Type type1Instance = ServiceLocator.CreateLibrary1Type();

                ILibrary2Type type2Instance = ServiceLocator.CreateLibrary2Type();

     

                Console.WriteLine(type1Instance);

                Console.WriteLine(type2Instance);

                Console.WriteLine("Press any key to exit");

                Console.ReadKey();

            }

        }

    } 

      

     

    Here’s my Service Locator implementation:

    using IsolatingTheNinja.Contracts;

    using Ninject;

    using Ninject.Modules;

     

    namespace IsolatingTheNinja.Services

    {

        public class ServiceLocator 

        {

            private static readonly IKernel _kernel = new StandardKernel(new INinjectModule[] { new Library1Module(), new

    Library2Module() });

     

            public static ILibrary1Type CreateLibrary1Type()

            {

                return _kernel.Get<ILibrary1Type>();

            }

            public static ILibrary2Type CreateLibrary2Type()

            {

                return _kernel.Get<ILibrary2Type>();

            }

        }

    }

      

     

    Here’s an example of my module:

    using IsolatingTheNinja.Contracts;

    using IsolatingTheNinja.Library1;

    using Ninject.Modules;

     

    namespace IsolatingTheNinja.Services

    {

        public class Library1Module : NinjectModule 

        {

            public override void Load()

            {

                Bind<ILibrary1Type>().To<Library1Type>();

            }

        }

    }

     

    The end result: SUCCESS. Ninject IS Stealthy! 

     Here’s the Source code

     

     

     

     

     

     

     

     

     

     

     

    Full story

    Comments (0)

  • Setting Up Fitnesse for C# .Net

    I use to use cory foy's example, but it's a bit dated now.

     

    Step 1:

    Download fitnesse

    http://fitnesse.org/FrontPage.FitNesseDevelopment.DownLoad

     

    click the fitnesse.jar link

     

    extract it to c:\fitnesse

     

    run java –jar fitnesse.jar –p [port]

    (If you want port 80 then leave off the –p and port)

     

    Navigate to http://localhost/ to try it out or http://localhost:[port]

     

    Step 2:

    Get fitsharp so you have the dlls for making fixtures and slim runner

    go to: http://github.com/jediwhale/fitsharp/downloads

    extract it to c:\fitnesse\slim

     

    Step 3:

    Make your test fixtures class library in visual studio

     

    Step 4:

    reference the fit and fitsharp dlls from c:\fitnesse\slim

    and reference any of your “System under test” dlls. (your dlls that your system uses that you want to test)

     

    Step 5:

    Write a fixture

    using fit;

     

    namespace Fitnesse

    {

        public class CalculateDiscount : ColumnFixture

        {

        }

    }

     

    Step 6:

    Make your first wiki page.

    Such as editing the front page and adding MyFirstFitnessePage

    It will show up like this after you save it:

    MyFirstFitnessePage?

    Click on the ‘?’ to create it.

     

    Step 7: make it a test page

    go to properties and change it to a “test” page.

     

    Step 8: Add all this stuff to the top of it

    !define TEST_SYSTEM {slim}

    !define COMMAND_PATTERN {%m -r

    fitSharp.Slim.Service.Runner,C:\Fitnesse\slim\fitsharp.dll %p}

    !define TEST_RUNNER {C:\Fitnesse\slim\Runner.exe}

    !path C:\projects\Fitnesse\Fitnesse\bin\Debug\Fitnesse.dll

     

    (the last line should be a direct path to your fixtures dll)

     

    Step 9:

    Make a test table

    |!-Fitnesse.CalculateDiscount-!|

    |amount     |discount?    |

    |0          |0             |

    |100        |0             |

    |999        |0             |

    |1000       |0             |

    |1010       |50.5          |

    |1100       |55            |

    |1200       |60            |

    |2000       |1000          |

     

    the !- -! Syntax forces literal text so it won’t interpret “CalculateDiscount” as a wiki page link you’ll get an error like this if you don’t do it

     

    Could not find class CalculateDiscountATitleCreatePageHrefCalculateDiscountEditNonExistentTrueA

     

    Apparently “ATitleCreatePageHrefCalculateDiscountEditNonExistentTrueA” gets appended when the ? is next to it.

     

     

     

    Full story

    Comments (0)

  • NHibernate basic 2 table example

    I’m slowly becoming intrigued by NHibernate and was playing around with it against AdventureWorks tonight.

     

    I came up with this basic 2 table tutorial using Employee and Contact.

     

    First, I created a wpf project for my user interface and I slapped a ListView on the main window like this:

    <Window x:Class="NHAdventureWorks.Window1"

        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="Window1" Height="300" Width="300"

         Loaded="Window_Loaded">

        <Grid>

            <ListView x:Name="lvwEmployees">

                

            </ListView>

        </Grid>

    </Window>

     

    Then I hooked up the Loaded Event:

    private void Window_Loaded(object sender, RoutedEventArgs e)

            {

                this.lvwEmployees.ItemsSource = LoadEmployeesFromDatabase();

            }

     

    Then I added this code from the ‘hello world’ example in Manning’s “NHibernate in action” book:

            static ISession OpenSession()

            {

                if (factory == null)

                {

                    Configuration c = new Configuration();

                    //c.AddClass(typeof(Employee));

                    c.AddAssembly(Assembly.GetCallingAssembly());

                    factory = c.BuildSessionFactory();

                }

                return factory.OpenSession();

            }

            static ISessionFactory factory;

     

            static IList<Employee> LoadEmployeesFromDatabase()

            {

                using (ISession session = OpenSession())

                {

                    IQuery query = session.CreateQuery(

                    "from Employee as emp order by emp.Contact.LastName asc");

                    IList<Employee> foundEmployees = query.List<Employee>();

                    return foundEmployees;

                }

            }

     

    Then I declared my domain model classes Employee and Contact as such:

        internal class Employee

        {

            internal int EmployeeId;

            internal string LoginId;

            internal Contact Contact { get; set; }

            internal int ContactId;

            public override string ToString()

            {

                return string.Format("{0} : {1} {2}", LoginId, Contact.FirstName, Contact.LastName);

            }

     

        }

        internal class Contact

        {

            internal int ContactId;

            internal string FirstName;

            internal string LastName;

     

        }

     

    Then I had to do the NHibernate specific stuff. First I added an xml file to the project called Employee.hbm.xml and then changed it’s build action to “Embedded Resource” (VERY IMPORTANT)

    Then I added a Contact.hbm.xml file as well (also marked as Embedded Resource). Then their contents looked like this respectively:

     

    <?xml version="1.0"?>

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

    auto-import="true">

      <class name="NHAdventureWorks.Employee, NHAdventureWorks"

             table="HumanResources.Employee" lazy="false">

        <id name="EmployeeId"

            column="EmployeeID"

            access="field">

          <generator class="native" />

        </id>

        <property name="LoginId" access="field" column="LoginID"/>

        <many-to-one

          name="Contact"

          column="ContactID"

          class="NHAdventureWorks.Contact, NHAdventureWorks"

          not-null="true" />

      </class>

    </hibernate-mapping>

     

    <?xml version="1.0"?>

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"

    auto-import="true">

      <class name="NHAdventureWorks.Contact, NHAdventureWorks"

             table="Person.Contact"

             lazy="false">

        <id name="ContactId"

           column="ContactID"

           access="field">

          <generator class="native" />

        </id>

        <property name="FirstName" access="field" column="FirstName"/>

        <property name="LastName" access="field" column="LastName"/>

      </class>

    </hibernate-mapping>

     

    Of course there are some app.config settings that had to be put into place:

    <?xml version="1.0" encoding="utf-8" ?>

    <configuration>

      <configSections>

        <section name="hibernate-configuration"

                 type="NHibernate.Cfg.ConfigurationSectionHandler, NHibernate" />

        <section name="log4net"

                 type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />

      </configSections>

      <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">

        <session-factory>

          <property name="connection.provider">

            NHibernate.Connection.DriverConnectionProvider

          </property>

          <property name="connection.driver_class">

            NHibernate.Driver.SqlClientDriver

          </property>

          <property name="connection.connection_string">

            Server=(local);database=AdventureWorks;Integrated Security=SSPI;

          </property>

          <property name="dialect">

            NHibernate.Dialect.MsSql2000Dialect

          </property>

          <property name="show_sql">

            false

          </property>

          <property name='proxyfactory.factory_class'>NHibernate.ByteCode.LinFu.ProxyFactoryFactory, NHibernate.ByteCode.LinFu</property>

        </session-factory>

      </hibernate-configuration>

      <log4net>

        <appender name="ConsoleAppender"

        type="log4net.Appender.ConsoleAppender, log4net">

          <layout type="log4net.Layout.PatternLayout, log4net">

            <param name="ConversionPattern" value="%m" />

          </layout>

        </appender>

        <root>

          <priority value="WARN" />

          <appender-ref ref="ConsoleAppender" />

        </root>

      </log4net>

    </configuration>

    Full story

    Comments (0)

  1. 1
  2. 2
  3. Next page