Embedding JUnit tests

Discussions

News: Embedding JUnit tests

  1. Embedding JUnit tests (45 messages)

    Bruce Eckel has written about embedding unit tests in our code. He discusses JUnitDoclet, and then goes on to show his own solution, which embeds the unit test within /*~ unit test code */ code. Personally, it makes a small file look rather large to me... but what do you think?

    Code Example
    //: c15:CountedListEmbedded.java
    // Embedded comments to generate JUnit tests
    import java.util.*;
    import junit.framework.*;

    public class CountedListEmbedded extends ArrayList {
      private static int counter = 0;
      private int id = counter++;
      public CountedListEmbedded() {
        System.out.println("CountedListEmbedded #" + id);
      }
      public int getId() { return id; }
      /*~ TestCountedListEmbedded
      // package statement goes here if necessary
      import java.util.*; // Any imports go here
      private CountedListEmbedded list =
        new CountedListEmbedded();
      public TestCountedListEmbedded() {
        for(int i = 0; i < 3; i++)
          list.add("" + i);
      }
      protected void setUp() {
        System.out.println("Set up for " + list.getId());
      }
      public void tearDown() {
        System.out.println("Tearing down " + list.getId());
      }
      private void
      compare(CountedListEmbedded lst, String[] strs) {
        Object[] array = lst.toArray();
        assertTrue("Arrays not the same length",
          array.length == strs.length);
        for(int i = 0; i < array.length; i++)
          assertEquals(strs[i], (String)array[i]);
      }
      */
      // The methods to be tested are shown
      // redundantly here, as a demonstration:
      public void add(int index, Object element) {
        super.add(index, element);
      }
      /*~ testInsert
        System.out.println("Running testInsert()");
        assertEquals(list.size(), 3);
        list.add(1, "Insert");
        assertEquals(list.size(), 4);
        assertEquals(list.get(1), "Insert");
      */
      // A method to be tested:
      public Object set(int index, Object element) {
        return super.set(index, element);
      }
      /*~ testReplace
        System.out.println("Running testReplace()");
        assertEquals(list.size(), 3);
        list.set(1, "Replace");
        assertEquals(list.size(), 3);
        assertEquals(list.get(1), "Replace");
      */
      /*~ testOrder
        System.out.println("Running testOrder()");
        compare(list, new String[] { "0", "1", "2" });
      */
      // A method to be tested:
      public Object remove(int index) {
        return super.remove(index);
      }
      /*~ testRemove
        System.out.println("Running testRemove()");
        assertEquals(list.size(), 3);
        list.remove(1);
        assertEquals(list.size(), 2);
        compare(list, new String[] { "0", "2" });
      */
      // A method to be tested:
      public boolean addAll(Collection c) {
        return super.addAll(c);
      }
      /*~ testAddAll
        System.out.println("Running testAddAll()");
        list.addAll(Arrays.asList(new Object[] {
          "An", "African", "Swallow"}));
        assertEquals(list.size(), 6);
        compare(list, new String[] { "0", "1", "2",
           "An", "African", "Swallow" });
      */
    } ///:~
    Read Bruce Eckel in Embedding JUnit tests

    Threaded Messages (45)

  2. Embedding JUnit tests[ Go to top ]

    I didn't read the article so I don't know Eckel's reasoning behind this idea. But I don't have to read the article to know that it looks awful. Why would I want to make my code practically unreadable?
  3. Embedding JUnit tests[ Go to top ]

    I really don't see the benefit to this but more unnecessary complexity being added to my code. There are packaages out there for that. Use them.


    -M
  4. One of the nice things about Java's exception handling is that it allows you to separate normal from error handling code. (Something that Bruce goes on about in Thinking in Java). However, you end up with awful code like:


    Object o;
    try {
      o = getObjectFromSomewhere();
    } catch (Exception e) { /* I can't write good code */

    o.doSomething(); // NullPointerException
    </pe>

    Now Bruce is suggesting that we do the same thing with test code? Instead of having one file containing the 'real' code, and another file containing the 'test' code, he wants to interleave these on a method by method basis? For god's sake, WHY?

    Secondly, this really puts a limit on setup steps (getting dummy objects, for example) or even tests that require multiple classes to wok.

    What should be done is to have some kind of declarative syntax saying what should be required, and then an external tool generate the test code.

    Really, really horrible.
  5. Considering how easy it is to have multiple source directories in most modern IDEs, I fail to see why this would be useful. However, I suppose if you want to go nuts with small tests like this, Eiffel stype PRE and POST comments would be much more clear and reasonably easy to automatically generate test code for. At least then it would look more like documentation than this nonsense.

    Yet another nail in the coffin of Bruce Eckel's Java credibility.
  6. Awful[ Go to top ]

    What a horrible idea.

    On top of what everybody said above, I will add:

    - It probably makes refactoring really fun.
    - Now you have two-pass compilation: your code first, then the tests. And back to square one if your tests don't compile since modifying them will modify your code as well.

    I thought that adding design by contract (precondition, postcondition and invariant) in comments was already a bad idea, but this one is worse.

    Having tests and code in sync is an "infrastructure" problem, not a coding problem. Solve it with packages, ant and/or your IDE of choice.

    --
    Cedric
    http://beust.com/weblog
  7. Awful[ Go to top ]

    Yeah very awful. Anyone who has written more than a few unit tests knows how impractical this idea is.

    I'm a ultra-lazy guy myself but he seems to be even lazier! I mean all his ideas and opinions show it! Small code snippets for books are bad for your programming health ;-)

    Ara.
  8. Awful[ Go to top ]

    1. Keeping the code and the test in the same file will, also, cause problems when you want to lock down the src tree in a source control environment. Our projects often lock the code, while leaving the tests still available for edit.

    2. JUnit tests can be a good place to start when trying to learn code that is new to you. That would be lost with this method.

    Tests and code should not be commingled.
  9. I agree with all the comments already posted, and I am really surprised with those "innovations".

    I thought that it was nearly standart to create the test classes in the same package but in a parallel directory.

      src/java/my/package/MyClass.java
      src/test/my/package/MyClassTest.java

    Or as a inner class when you need to test private methods.

    Cheers
      JD
  10. I thought that it was nearly standart to create the test classes in the same package but in a parallel directory. src/java/my/package/MyClass.java src/test/my/package/MyClassTest.javaOr as a inner class when you need to test private methods.Cheers JD
    Tests should have the same package, but should live in a different project/directory. IDEs (and/or ant scripts) make this technique very easy.
    To test private methods I prefer to use reflection.
    Cheers,
    Stefan
  11. Tests should have the same package, but should live in a different project/directory. IDEs (and/or ant scripts) make this technique very easy.To test private methods I prefer to use reflection.Cheers,Stefan
    I do not want to advocate this way too mutch, because I have never used it myself,
     but as I understand it was invented to "integrate" code and test, private method feature is just more cool than usefull, I see no problems to drop "private" modifier if it helps to test code.
  12. Or as a inner class when you need to test private methods.Cheers  JD
    You never should test private methods.
  13. Why "never" test private methods?[ Go to top ]

    You never should test private methods.
    Why not? It is useful on occasion. Never say never.
  14. Why "never" test private methods?[ Go to top ]

    The use of inner classes change the semantic of the private modifier.... private method in class with inner classes are not private... they become package private.

    So it's the same to remove the private modifier and to put your test in the same package in a different source tree. But having them separate allow you to more easily package only your production code by not compiling the test code.
  15. You never should test private methods.
    Please give a very good reason for this.
  16. You never should test private methods.
    Please give a very good reason for this.
    You can't do it with jUnit ;)
    Thats why Thought Leaders recommend that you *should* not test private methods...
    By the way, who wrote jUnit?
  17. Embedding JUnit tests[ Go to top ]

    It is a good idea to keep code and test in the same file, but not in comments.
    A good way to do it is to implement inner class for tests:

    public class MyClass {

      public static class Test {
              
             public void testIt(){
                 Tests.assertEquals(doIt(0),0);
             }

      }

      private int doIt(int v){
          
            return v;

      }


    }

    I do not use it, but I think it is a good idea, it helps to test private methods and probably has more advantages . NetBeans IDE has support for this kind of test. Outer class have no runtime dependacy on test and there is no meaning to hide it in comment, but compile time dependancy is more a feature in this case.
    Probably I will change my way to test code too.
  18. Embedding JUnit tests[ Go to top ]

    It is a good idea to keep code and test in the same file, but not in comments.A good way to do it is to implement inner class for tests
    And then you ship your code with all the tests inside?!?

    Also, I wonder how you like it when QA keeps modifying your files to add their tests (and the other way around).

    --
    Cedric
  19. Embedding JUnit tests[ Go to top ]

    I join the majority here in saying that I think its not a good idea to mix code and test in such a way. All the arguments against this have been said.

    If you want something alongside the code, then use Design by Contract, like IContract.

    I wonder how such a famous programmer can have such an bad idea.
  20. Embedding JUnit tests[ Go to top ]

    And then you ship your code with all the tests inside?!?
    -- Cedric
    An inner class compiles into its own class file. You can choose not to include these test classes in your shipped code.
  21. Embedding JUnit tests[ Go to top ]

    It is a good idea to keep code and test in the same file, but not in comments.A good way to do it is to implement inner class for tests
    And then you ship your code with all the tests inside?!?Also, I wonder how you like it when QA keeps modifying your files to add their tests (and the other way around).-- Cedric
    I do not think there is some difficulties to modify inner class or not, I hope it is better to have code and test integrated as more as possible. I am not going to use test in comments, but I am going to try "inner class test", it is trivial to refactor if this experiment will fail.
  22. it gives new meaning to TDD[ Go to top ]

    I can't see any usefulness in this co-mingling of your test codes with your production. I understand if Bruce was thinking about letting Test drives the design of the system. But this is taking it too far.

    It's good that the test and the production code is "closely tight" but it has big managability, readability issues among other things
  23. Embedding JUnit tests[ Go to top ]

    I am not going to use test in comments, but I am going to try "inner class test", it is trivial to refactor if this experiment will fail.
    I don't agree, but the inner class is way better than his comment.
  24. Nested JUnit tests[ Go to top ]

    Nesting JUnit test classes works quite well -- the few disadvantages mentioned can be dealt with easily. I've been using this approach for a while, see my writeup at http://www.ideanest.com/blog/item/18.
  25. too many lines in a class[ Go to top ]

    it will make too many lines in a class, i don't think i would use it. In my project , i always use a package(or more) for my test cases classes.
  26. Embedding JUnit tests[ Go to top ]

    How do IDE's support java code within comments (code coloring, code completion, error detection, import expansion, refactoring, ...)?

    Not at all. Why should they? There are other (enough) means to structure code and to separate test code.
  27. Embedding JUnit tests[ Go to top ]

    I also think it is really awful to have test code in your class!!! In my project, I used to organize tests in seperate packages, now I adopted the approach to kep them under same package but the class name will start with __. So, when you browse, you can easily ignore them, your build scripts can exclude them. Main advantage will be avoid expose package method to public only for test reason.
  28. Yeh[ Go to top ]

    It would be nice to have the test's located along with the source, however the above example is way too busy looking. Having separate tasks seems inelegant.

    public class BankAcct {

    float bal;

    public void setBalance(float newBal) { this.bal = newBal; }
    public float getBalance() { return this.bal; }

    public void deposit(float amt) { this.bal+=amt; }
    public void withdraw(float amt) { this.bal-=amt; }

    /*
    test { // Implicit test object instantiation
    .setBalance(100);
    .withdraw(50);
    assertEquals(getBalance(),50);
    }
    */


    }

    Or XML of course...
  29. the spherical horse in vacuum[ Go to top ]

    There was an old Russian joke about the physicist who was awarded a grant to research a theory behind winning horse races. After a year or so of very sophisticated work, he was asked by those who gave him a grant: "So, how it's going?" "Yep", said the scientist, "it's going pretty well. I've already build a model for spherical horse in vacuum!"

    Back to unit tests, from my experience it follows that the major (~90%) of all unit tests development efforts are required to set up fair test fixture. But here, we see just 'spherical horse in vacuum', nothing more:

    protected void setUp() {
     System.out.println("Set up for " + list.getId());
    }

    I'm just so tired of those extremely simple unit test examples, which never go further than testing just stupid stateless class whose lifecycle is straight and short. How many of your classes are looking like that CountedListWhatever?

    Finally, back to topic - no I don't think at all that it's good idea to mix unit test code with actual code:
    - it mixes two very separate concerns into one incomprehendable goo
    - it doesn't allow design unit tests to reuse parts of their fixtures for similar classes
  30. Linking JUnit tests[ Go to top ]

    Another -1!

    What I would like to have is IDE support. I would like to be able to navigate to the test case from the source with a single key storke. May be with the advent of annotations future IDEs will support that.
  31. Linking JUnit tests[ Go to top ]

    IntelliJ has that feature ... if you install the utest plugin.
  32. What a great idea[ Go to top ]

    Now, when tests look like comments, we can treat them as comments: No comments.
  33. Embedding JUnit tests[ Go to top ]

    fail("a fine art rewards adding some comments, but not my code!");
  34. Yikes![ Go to top ]

    Terrible idea. Beyond the obvious objections to its degradation of code simplicity and clarity, I disagree with Eckel's claim that it's a problem to switch back and forth between a TestCase and its tested code. Writing a test does not (and in fact should not) require knowledge of the implementation of the method it tests. You're testing to an interface, not to an implementation. That's one of the primary benefits of unit tests: you can regression test future implementation changes. Writing tests "test-first" (with many benefits one can read about in several books) means you don't even have the "to-be-tested code" to look at anyway. All you really need is an IDE that that autocompletes method names.

    To me, this seems like a solution looking for a problem.
  35. losing credibility[ Go to top ]

    Wow, Bruce appears to be losing credibility. I haven't seen a favorable Bruce Eckel post in a long time.
  36. just use a modern IDE please[ Go to top ]

    navigation between related information, like source and test, is no longer a problem.
  37. Good Idea but bad place...[ Go to top ]

    Good idea
      because the IDE's can add comments to generate test-cases.

    Bad place
      Java comments are not the place to write test-cases. Common guys...
  38. Embedding JUnit tests[ Go to top ]

    Wow. Just ...
    wow.
    This is one of the dumbest things I've heard in a long time.

    I've spent a lot of time recently with one of my clients getting them to unit test their code. One of the biggest selling points is that your design improves by writing tests in parallel or beforehand. Your tests become your first client application, helping shake out your ideas about the class design and access. That's completely lost with this approach. Along with readability, separation of concerns, ability to modify tests without touching source, and countless other reasons why unit testing is good. If you want to simplify unit testing, use groovy or something. Don't simplify unit testing at the expense of complicating your actual code. That's just dumb.

    I don't know what this idea is in response to. But I do know that I can't wait to see the bile blog take it on.
  39. Dont believe it is such a bad idea! Sure.. for multi class testing, and disciplined IDE based environments this is this is prob not very useful. But dont believe that was the pitch anyway. The utility is essentially for single class unit testing.

    How many projects do full justice to the lowest level unit testing!? Here it surely makes sense to have an approach which minimizes any impedence to getting these tests in.

    Further, this is akin to having comments (even if a bit ugly ;-) ) describing the method. Instead of comments, capture the same as 'assertions' of the functionality to be provided by the method. And by using the proposed syntax, ensuring there is a unit test to excrcise and verify the same. If the assertions are right above the method, anytime the logic/code changes in the method, it is easy to ensure that the 'assertions' are changed accordingly.

    Sure.. code looks ugly. This is a downside. But compared to not having unit tests, this is probably better!

    Cheers,
    Ramesh
  40. I must admit that I find the basic idea okay; it is always good for maintainability to have related code placed together as much as possible. E.g. I always place the declaration, getter and setter next to each other instead of sorted (my IDE can do that for me in a list view :-) ).

    Usually doing something like this also improves readibilty of the code, especially if you include some nice commented separators, but this make codes look like a total mess. And readiblity comes first in the list of code style priorities.

    Nice idea, bad implementation.

    For simple tests, would it be possible to simplify the testing code to a few doclets statements (and for example auto import all the classes that are also imported by the to-be-tested class)? Or create testing code based on the JDK1.4 assert statements?
  41. Embedding JUnit tests[ Go to top ]

    This is like one of those bad TV advertisements. The presenter articulately explains a problem no one really has or can easily solve, then they to try to sell you a product that solves it for you.

    For a brief instant you actually try to evaluate the product on its merits, then it occurs to you "I don't have this problem", and you change the channel...
  42. Late April fools' joke?[ Go to top ]

    Was the original post date April 1?
  43. New ideas for an IDE[ Go to top ]

    I am having a hard time going from the visual in my head to an explanation, but this gives me some ideas for an IDE. One of the nice things about .NET is the assumption that you will be using VS.NET for writing code. This assumption created things like regions. In notepad a region is useless, but in VS it is great. I can hide away my region of boilerplate code and the text is much more readable. Also, the embedding of metadata in the code is nice, when used correctly, it makes it much more readable. Simple things like putting [Web Method] or [Test] (with NUnit) are great.<br>
    This got me thinking. If java added some features like metadata, that allowed me to specify where a test for a particualr method was located, then just hovering over the [TestLocation("MyTestFixture.MyTest")] could bring up the test code in a baloon. Clicking on this baloon could take me to the test where I can edit it. This could work both ways if the test knew where the actual code was located. In theory this idea could be extended, clicking on this baloon could pop up a hovering textarea that is syntax aware and contains an editable version of my test. my test is still stored somewhere else, but I can view and edit it without losing sight of my code. I gain the advanage of what bruce is showing, while keeping my code clean and easy to read.
  44. Embedding JUnit tests[ Go to top ]

    I've blogged a bit on this subject if anyone is interested. Yeah, I agree with most people that the idea itself is pretty stupid. But the dumb idea is masking an even dumber one - writing unit tests that are so finely granular that they effectively tell you nothing. If Eckel wants to further the state of software development today, maybe he should write an article on integration or performance testing, not yet another Thought Leader article on how to test:

      i = 5;
      i = i + 1;
      assert i == 6;

    Like, yeah, I really want to live with a system that has 3 times as much stupid low-level testing code as real code, and put myself in a box where I don't even have the time to consider integration testing, let alone actually code it.
        -Mike
  45. Makes the code very hard to read[ Go to top ]

    I find it to be an interesting idea, but ...

    Just doesn't seem very usable. Makes the code very hard to read.

    overall

    -1
  46. Embedding JUnit tests[ Go to top ]

    Personally, I rather like the idea but I would change the layout a bit.
    I don't mind whitespace but I'd like to be able to see "what the code does"/actual comments and the test code out of the way a little so one idea might be to tab the tests over to about 40 like this:

    /**
     *
     */
    public void doX()
    {
      ...
    }
                         /* ~testdoX
                             ...
                          */
    /**
     *
     */
    public void doY()
    {
      ...
    }
                        /* ~testDoY
                            ...
                         */