nullpointer.at

TDD Exam Question Answers


A few days ago, i saw the blog post from codecop Peter about test driven development exam questions. First time i read it, i thought some of the questions are not specific enough. Other Questions seamed easy to answer and some may be trick questions. But i didn’t deal with them intensively.

A bit later, the blog post was promoted on twitter again by an other developer and i took a second approach. Because i’ve posted so much pictures in the past weeks and a very limited number of development related blog posts, i’ve decided to answer these questions here. If i’m wrong or if i answerd incomplete, feel free to comment and help me getting things right. You in particular Peter! Just by watching TDD from Hell and reading some TDD blog articles, i will need advice on some of the questions.

But enough about the circumstances, lets face em:

Unit Testing with JUnit

Lets assume first, that all the questisons deal with Junit 4.x.

What is a test fixture?

Test fixture describes the setting of a test. If you want to run a test several times, you have to ensure that the software starts everytime in the same state and the prerequisites are all well known. In JUnit you can archive this within the setUp() and tearDown() methods.

Which assert is used to compare the values of objects?

Assert.assertEqual(String message, Object expected, Object actual); for more details on this and other Object related assertEqual variants see Junit Javadoc. Needed to take a look myself alsways mixing up the method signature with the one of TestNG.

What about assertTrue(true);?

Is this some kind of a trick question? Why should anybody implement it this way? To check if assertTrue works? Well the test will succeed. Simply as it is, the boolean condition given to the method will be checked. If you want to compare the value of two objects with assertTrue, you have to write the condition on your own. See such a condition within the next question.

What about assertTrue(a.equals(b));?

As mentioned before this will determinate if the boolean condition given will be true. But let’s take this as a chance to look the code of assertTrue on Github. Very simple, isn’t it? You can see there, that a method with an additional message parameter is called. You should prefer writing a short message about the failed test, to help others determinate the error easier.

How to test for an expected exception?

Well i’ve got 3 soltions, non looking nice and smooth:

Simply do it yourself
@Test
public void testException(){
   try{
      expressionShouldFail();
      fail("expression should fail because of ... but didn't!"
   } catch (RuntimeException e){

   }
}

ugly empty block :/

Expected Parameter
@Test(expected = RuntimeException.class)
public void testException(){
   expressionShouldFail();
}

but wait – there is no space for my message!

Expected Exception Rule
@Rule
public ExpectedException expectedEx = ExpectedException.none();

@Test
public void testException() {
   expectedEx.expect(RuntimeException.class);
   expectedEx.expectMessage("expression should fail because of ... but didn't!");

   expressionShouldFail();
}

so now we’ve got the message again, but at the cost of several new lines. I’d wish there would be some kind of @Test(expected = RuntimeException.class, expectedMessage= „expression should fail because of … but didn’t!“)

What about System.out.println(…); in tests?

Well it works within tests, but tests are made for automation so they won’t be read much. Use the Assert message instead!

How to data-drive tests?

Well i don’t know exactly what was meant with data-drive tests, but i’ve associated it with parameterized tests.

// So you will need a JUnitRunner first
@RunWith(value = Parameterized.class)
public class ParamTest {

   // Also this will need some Fields holding the values for each data set
   private int data;

   // and a constructor for setting them.
   public ParamTest(int data) {
      this.data = data;
   }

   // The Parameters are supplied by an annotated method as a Collection<Object[][]>
   @Parameters
   public static Collection<Object[]> data() {
      Object[][] data = new Object[][] { { 665 }, { 666 }, { 667 } };
      return Arrays.asList(data);
   }

   // The test itself can use the field for it's check
   @Test
   public void pushTest() {
      Assert.assertTrue(666 <= data);
   }

}

I see three drawbacks with this solution, i’ll list shortly:
– only one testcase in one class is possible and clear (this is perhaps a design question if it is really a drawback)
– if more than one parameter (e.g. an additional message String) it’s very confusing and hard to read code in the @Parameters method
– debugging needs more actions the more data sets you’ve got

How to time-out tests?

Similar to the expected parameter for the @Test annotation there is a timeout parameter. It is used to set the amount of milliseconds a test is allowed to run at max. If it takes longer to run, the test will fail.

How to test the contents of a private field? (This is a trap, the answer is not to test it but to change the design.)

Well you could ue reflection to gain access if it’s really necessary. But as Peter mentioned, change the design!

Does full code coverage mean the code is fully tested?

No, no and no! Seriously no! You won’t catch all possibilities and faults. It is a start, but don’t overdo your coverage. Add new tests simulating bugs found when maintaining the software. And remember that there are differences in line, branch, statement, class, package, … coverage.

That’s it for Unit Testing. Want to read more about Unit Testing? See the links below.

Test Driven Development

What are the benefits of using TDD?

The first theoretical question with a wide range of answers. But i’ve found some points:

  • It let you think first – you have to know what the code should do before you write it.
  • It provides a short feedback loop, you can see if your coding works in a fast, repeatable way, no ui-klicking and self-simulating.
  • Improved safty when refactoring – if you want to refactor code, you can easily check for regressions, so you can save time with it too.
  • Simplification – you only write code to match the testcases, small classes focusing on one thing (SRP).
  • The unit tests could be used as some kind of documentation of the behaviour of the code.

All those things helps to improve quality, reduces bugs and hopefully leads to more enjoyment.

Is TDD primarily a testing technique?

I’d call it a working technique, or more specific a programming technique. It is about doing things, new things and changes.

When do you write tests? (This is a joke and the expected answer is „all the f*cking time“ according to Bryan Liles‘ TATFT.)

I’ve read some blog posts about when to write and when to not write tests, and it was stated out that you maybe can overdo testing very simple methods. But when there is a fault you will wish you’d written some ;) – If you do TDD you write them all the time.

What should you do when you cannot add another test?

Perhaps you are finished! Time to refactor! And if not – change your design :D and if it’s an problem of the environment perhaps change it?

If the code passes all the unit tests why should you still change (refactor) it?

Because you can improve it (e.g. remove duplications) and making it cleaner and more readable (e.g. by finding better names for variables and method). If all your tests pass, it’s the best time to refactor, because you will get instant feedback if you broke the behaviour of the refactored parts by running the tests.

Why not refactor on a red bar?

Well your solution is not working now, if you refactor it now, you’ll propably get a bigger mess because you can not determinate if the things you do do work.

Mocking and Test Doubles

Why use stubs or mocks?

Use them to have some fixture for your test. If you want to test class A and it depends on functions in class B and C you can test each of them seperatly by using stubs and mocks. So if you break the implementation of B only the tests of B will fail and you won’t have to start searching for the regression in A.

How are objects called that are passed around but never actually used?

Dummys – You can use dummys to fill parameter lists.

How are objects called that can return fixed values in answer to calls made.

They are called stubs. And according to wikipedia they are usually not responding to anything besides the implemented calls.

How are objects called that can verify the behaviour of the system under test, in addition to using asserts to verify its state.

Mocks – e.g. with mocks you can check the order in which it’s methods have been invoked. See wikipedia to read more.

What is used for testing state?

Stubs – because it does not check any behaviour, they just do what expected without order or parameterization.

What is used for testing behaviour?

Mocks – as mentioned above they have the ability to check themself and therefore verify if the were used in a correct manner

What is a spy?

A spy has a similar behaviour as a mock. The main difference is that a mock’s behaviour has to be defined before the target method is invoced.

Refactoring

What is your favourite Refactoring?

Well, a green-bar refactoring ;)

How do we refactor? (This is a word play and the expected answer is mercilessly.)

mercilessly! (you wanted to hear that!)

Should Refactoring and adding new code be done at the same time?

Green-bar refactoring! Not at the exact same time, because it is easier to distinguish between new failures or existing regressions.

During Refactoring, how long does your code not compile?

As long as i’ve not found the missing semikolon ;) – in other words, it should compile every time! (compile != work)

During Refactoring, when should we run the tests?

Run the test before the refactoring to verify that the behaviour is correct. And run it afterwards to see that your work is correct too. If the test at the beginning of the refactoring fails, fix it first before you start your refactoring.

What Refactoring can be used when a method is too long, has duplicated code or Feature Envy?

Extract a method, a class or a component.

What Refactoring can be applied to long parameter lists?

Pass object holding the values to the receiver or let the receiver invoke calculation of other parameters. If you don’t want to pass the whole object you can define additional value objects holding only the values needed.

In Eclipse, what do the short-cuts Alt-Shift-R, Alt-Shift-L and Alt-Shift-M do?

You don’t know it? Mouseuser!
Alt-Shift-R – Rename
Alt-Shift-L – Extract Local Variable
Alt-Shift-M – Extract Method
See my eclipse-shortcut blog post for additional ones!

Working with Legacy Code

What is Legacy Code?

Source code is called legacy code if it, or the operation system it needs, is no longer supportet.

How can you break dependencies?

Don’t know if that anser is so simple: Extract functionality into new Classes and use Dependency Incejtion to loose coupling

What are Singletons and why are they evil?

It’s a design pattern limiting the instantiation of a class to only one object.
When they are used as a global instance they hide dependencies instead of exposing them through interfaces. They increase coupling and these leads additionally to difficult to test code. And they can carry state around for the whole lifetime of an application. This is difficult to handle in multi-threaded environments and it propably has effects on the order of testcases. Ah, i’ve seen the link to a more complete liste to late. Go there for further reading.

Do you write them?

Sure! ahhh i mean: in the past… ;)

Fin

So my answers got shorter in the end, it was late and admittedly, i’m not experienced with refactoring Legacy Code. So now it’s your turn to add what i’ve missed.

Some links for further reading

Homepage of Junit – http://junit.org/
Recommendations from Peter – http://blog.code-cop.org/2012/04/junit-tutorials.html
About Mocking – http://martinfowler.com/articles/mocksArentStubs.html

Ähnliche Artikel:

  • Noch keine vorhanden.

Beitrag veröffentlicht

in

von

Kommentare

2 Antworten zu „TDD Exam Question Answers“

  1. Avatar von Peter Kofler

    Tom, thanks for the answers. You got most right. Here are just a few comments as food for thought for you:

    assertTrue(true); – I have seen that in code bases that checked if every test method had an assert. As you say it is useless. Write a proper assertion.

    assertTrue(a.equals(b)); – think about the message you get in case of failure, how can we get a better message?

    What should you do when you cannot add another test? – See slide 7 of Nat Pryce (http://www.doc.ic.ac.uk/~np2/teaching/mock-objects-slides.pdf) for a nice image.

    What is Legacy Code? – there is a clear definition by Michael Feathers. Also Adi Bolboaca says you can have legacy code after 10 minutes of coding.

    How can you break dependencies? – refer to Michael Feathers‘ book on working with legacy code.

    1. Avatar von Pummer Thomas

      Hi Peter,
      thank you for your fast response! Glad that i got most :) And interesting hints for further reading!
      Greetings

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

*