Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [linux-distros-dev] 0.2 + agile development



On 6/3/09 20:50, Andrew Overholt wrote:
   - mocking frameworks, to mock out interfaces and test if listeners are
invoked among other things (I recommend mockito[4])

EasyMock is in Orbit, right?  We often find that we get hung up writing
tests because our tools are interacting with native tools that aren't
necessarily on build.eclipse.org but *are* on the developer's box and
thus it's too easy to just Runtime.exec them.

I've used mockito, that grew out of the learnings of EasyMock and has improvised on a lot of EasyMock features.

Mockito is seriously addictive within 1 hour of using it, and EasyMock comes nowhere close to it. I say this from an experience of using and contributing to EasyMock, JMock and Mockito :)

That said using EasyMock is better than having nothing at all!

> Mocking up output of
these tools would help a lot.  In fact, I have an example:

Utils.runCommandToString("rpm", "-q", pkgName, "--qf", \
   getformattedRpmInformations());

What's the best way to be testing that we're getting the correct output
of rpm -q?  I guess we have to assume that rpm itself is functioning
correctly (and handle errors) and pretend we got the information from
the command?  Perhaps this is an area we need to refactor if it's not
easy to drop in a mock object?


Mocking requires that there's no use of statics. Mocking relies on using java proxy objects and therefore needs that you use interfaces(http://martinfowler.com/articles/mocksArentStubs.html) that you can mock or stub. Statics and singletons hamper testability to the point that it makes objects difficult if not impossible to test. We've learnt this the hard way when writing tests for eclipse plugins, since writing tests before writing code is a way of life where I work.

One way I can see this test being written is:

public interface Executor {
  String execute(String command, String... args);
}

Then you could have a test that mocks the implementation (uses hamcrest):

public void testExecutorReturnsCorrectString(){
  Executor e = mock(Executor.class);
when(e.execute("rpm", "-qil", "libxslt-devel")).thenReturn("output of rpm command");

  Dependencies d = new RPMDependencyParser(e).parse();

// run your test on whether the dependency parser worked, without worrying about whether the executor ran correctly
}

Or you could stub it out as:
public void testExecutorReturnsCorrectString(){
  Executor e = new Executor(){
    public String execute(String command, String... args){
      return "a list of dependencies";
    }
  }

  Dependencies d = new RPMDependencyParser(e).parse();
// run your test on whether the dependency parser worked, without worrying about whether the executor ran correctly.
}

Having a good interface, and dependency injection goes a long way in ensuring good design, and testability.

I could help out with providing tips on writing testable code, if you're interested in knowing more.

   - cobertura/eclemma for coverage reports [3]

Some of us have been using Eclemma on our local machines.  I want to get
emma integrated into the common builder at eclipse.org so we can see the
results in hudson.  Would this be of interest to you at all?

Hudson supports cobertura as well (not acting the devil's advocate here). Cobertura provides better reports than eclemma; eclemma provides better IDE integration. So it's upto the team to choose one.

After a while when I have a few thousand tests, I prefer to not run tests with code coverage turned on (since they tend to increase the test time by an order of magnitude) but still like to keep an eye on cruise when the test coverage drops.

-- Ketan


Back to the top