Loading ...
Sorry, an error occurred while loading the content.
 

Re: [XP] TDD and C++

Expand Messages
  • Ian Collins
    ... I must admit I ve never use CPPUnit-Lite, but it s quite simple to stick with a small subset of CPPUnit without too much fluff. Our testers, who had just
    Message 1 of 27 , Apr 1, 2006
      Tim Haughton wrote:

      >On 01/04/06, Alex Pukinskis <Alex.Pukinskis@...> wrote:
      >
      >
      >>I have taught TDD in other languages (Java, C#, PHP) but never in C++. Any
      >>big gotchas we should watch out for in this context?
      >>
      >>
      >
      >The only thing worth mentioning that I can think of relates to the
      >tools. If the team is completely new to TDD, I think I'd almost
      >certainly start with CPPUnit-Lite rather than CPPUnit. It's several
      >years since I used either of them, but I seem to remember CPPUnit as
      >being a little unwieldly.
      >
      >
      >
      I must admit I've never use CPPUnit-Lite, but it's quite simple to stick
      with a small subset of CPPUnit without too much fluff. Our testers, who
      had just learned C, had no trouble using it.

      >I wasn't into mocking back then, so I don't know of any C++ mocking
      >frameworks, if you come across one, post back :)
      >
      >
      >
      I think most teams roll their own, we did.

      Ian
    • Dean Wampler
      On a side note, is it necessary to use C++ for this project or perhaps for most of its subsystems? My last real job (before becoming a consultant ;) ) was at a
      Message 2 of 27 , Apr 2, 2006
        On a side note, is it necessary to use C++ for this project or perhaps
        for most of its subsystems? My last real job (before becoming a
        consultant ;) ) was at a telecom startup in Chicago. In our case, we
        *should* have used Java for most of our project, which was really very
        similar to a typical internet/enterprise-like application server in
        many ways. Some subsystems needed to be written in C++, such as those
        that handled streaming media and those that interfaced to 3rd-party
        C/C++ libraries for which there were no java equivalents. However, had
        we written the rest of the system in Java we could have leveraged many
        of the innovative tools and libraries that aren't available for C++.

        Even for a startup, our management was very conservative and wouldn't
        go along with this approach. Because we had a small team, the result
        was low productivity and difficulty responding quickly to changing
        customer requirements. I think we missed some opportunities as a
        result.

        You may not have a choice, but I would consider the options.

        My $0.02,
        dean

        On 3/31/06, Alex Pukinskis <Alex.Pukinskis@...> wrote:
        > I am working with a team that is developing telecom applications in C++.
        > So far, we're doing Scrum with user stories and plan to start adding in the
        > core XP practices within a few weeks (TDD, Simple Design, Refactoring, Pair
        > Programming).
        >
        > I have taught TDD in other languages (Java, C#, PHP) but never in C++. Any
        > big gotchas we should watch out for in this context?
        >
        > Anyone with some experience doing TDD in C++ willing to talk about their
        > experiences? Particularly in telecom, networking, or embedded applications?
        >
        > Thanks,
        >
        > -Alex
        >
        > --
        > Alex Pukinskis - Agile Coach
        > Rally Software Development - http://rallydev.com/
        >
        >
        >
        >
        > To Post a message, send it to: extremeprogramming@...
        >
        > To Unsubscribe, send a blank message to: extremeprogramming-unsubscribe@...
        >
        > ad-free courtesy of objectmentor.com
        > Yahoo! Groups Links
        >
        >
        >
        >
        >
        >
        >


        --
        Dean Wampler
        http://www.aspectprogramming.com
        http://www.newaspects.com
        http://www.contract4j.org
      • Graham Wright
        ... in C++. ... adding in the ... Refactoring, Pair ... C++. Any ... their ... applications? ... The main problem with C++ is that refactoring can be slower
        Message 3 of 27 , Apr 2, 2006
          --- In extremeprogramming@yahoogroups.com, Alex Pukinskis
          <Alex.Pukinskis@...> wrote:
          >
          > I am working with a team that is developing telecom applications
          in C++.
          > So far, we're doing Scrum with user stories and plan to start
          adding in the
          > core XP practices within a few weeks (TDD, Simple Design,
          Refactoring, Pair
          > Programming).
          >
          > I have taught TDD in other languages (Java, C#, PHP) but never in
          C++. Any
          > big gotchas we should watch out for in this context?
          >
          > Anyone with some experience doing TDD in C++ willing to talk about
          their
          > experiences? Particularly in telecom, networking, or embedded
          applications?
          >
          > Thanks,
          >
          > -Alex
          >
          > --
          > Alex Pukinskis - Agile Coach
          > Rally Software Development - http://rallydev.com/
          >

          The main problem with C++ is that refactoring can be slower than
          with Java or C# so do everything possible to avoid this by keeping
          classes small and cutting down on dependencies by using forward
          declaration instead of including secondary header files.

          C++ generally goes hand in hand with COM. If this is the case with
          your project reduce the need to test the COM components by using the
          envelope – letter pattern to forward all COM calls to a worker class
          that can be tested outside the COM runtime.
        • Ian Collins
          ... That s an odd generalisation! Ian
          Message 4 of 27 , Apr 2, 2006
            Graham Wright wrote:

            >C++ generally goes hand in hand with COM. If this is the case with
            >your project reduce the need to test the COM components by using the
            >envelope – letter pattern to forward all COM calls to a worker class
            >that can be tested outside the COM runtime.
            >
            >
            >
            That's an odd generalisation!

            Ian
          • Keith Ray
            The original poster mentioned embedded software, and if they were embedding using a Windows operating system, I would recommend that they re-think that
            Message 5 of 27 , Apr 2, 2006
              The original poster mentioned embedded software, and if they were
              embedding using a Windows operating system, I would recommend that
              they re-think that decision.

              > C++ generally goes hand in hand with COM. If this is the case with
              > your project reduce the need to test the COM components by using the
              > envelope – letter pattern to forward all COM calls to a worker class
              > that can be tested outside the COM runtime.

              --

              C. Keith Ray
              <http://homepage.mac.com/keithray/blog/index.html>
              <http://homepage.mac.com/keithray/xpminifaq.html>
              <http://homepage.mac.com/keithray/resume2.html>
            • Jason Almeter
              ... A port of xUnit will be handy. I wrote my own following along with Beck s TDD book. I would also recommend boost::shared_ptr to help ease memory
              Message 6 of 27 , Apr 2, 2006
                Alex Pukinskis <Alex.Pukinskis@...> writes:

                > I have taught TDD in other languages (Java, C#, PHP) but never in C++. Any
                > big gotchas we should watch out for in this context?
                >
                > Anyone with some experience doing TDD in C++ willing to talk about their
                > experiences? Particularly in telecom, networking, or embedded applications?

                A port of xUnit will be handy. I wrote my own following along with
                Beck's TDD book. I would also recommend boost::shared_ptr to help
                ease memory management and the pImpl idiom to reduce coupling.

                -Jason

                --

                jalmeter under 99 at yahoo
              • David Carlton
                ... Me too. The main mistake I made was not initially using RAII to set up and tear down tests. Have each test correspond to a class, and set things up so the
                Message 7 of 27 , Apr 2, 2006
                  On Sun, 02 Apr 2006 18:17:14 -0400, Jason Almeter <jalmeter_99@...> said:
                  > Alex Pukinskis <Alex.Pukinskis@...> writes:

                  >> Anyone with some experience doing TDD in C++ willing to talk about their
                  >> experiences? Particularly in telecom, networking, or embedded applications?

                  > A port of xUnit will be handy. I wrote my own following along with
                  > Beck's TDD book.

                  Me too.

                  The main mistake I made was not initially using RAII to set up and
                  tear down tests. Have each test correspond to a class, and set things
                  up so the class instance doesn't get constructed until you're about to
                  run it and the destructor gets called right after you run it. This
                  works a lot better than jUnit-style setUp and tearDown methods.

                  David Carlton
                  carlton@...
                • James Grenning
                  I d be happy to talk to you about it. We re working on a few Agile EMbedded projects. We ve evolved CppUnitLite into CppTestTools. CppTestTools has a unit
                  Message 8 of 27 , Apr 3, 2006
                    I'd be happy to talk to you about it. We're working on a few Agile
                    EMbedded projects. We've evolved CppUnitLite into CppTestTools.
                    CppTestTools has a unit tests harness based on CppUnitLite and it can
                    support FitNesse too. Right now the fitnesse tests only run on the
                    host machine. We are involved in embedded C++ projects using both tools.

                    CppTestTools is as easy to use as CppUnitLite but has a few other
                    capabilities. I am going to update CppTestTools in the next day or
                    two. They can be found on fitnesse.org.

                    Keep your code dual targeted as much as possible so that unit tests
                    can be run on both the host and the target. We spent less than a day
                    getting the unit test harness running on a Hitachi SH3 processor.
                    Unit tests we built and run first on the host where turn around time
                    is fast. Downloading to the target was a coffee break operation so
                    running only in the target was not practical. Also the desire to run
                    code two places results in a less machine dependent design.

                    Periodically we would run the unit tests on the target processors to
                    make sure there were no compiler/library differences. On day one we
                    discovered that the good old well defined C function strstr() worked
                    differently on host and target. I always thought dual targeted tests
                    were a good idea before that, and that gave me some hard evidence.

                    Dual targeting means you have to be careful about calling OS dependent
                    code. CppTestTools has a bit of example code in the Concurrency
                    library showing how one might stay independent of the OS. The
                    incomplete Concurrency library has example implementations for posix
                    and win32.

                    Being that it is so easy to leak memory in C++ CppTestTools has some
                    primitive memory leak detection built in. If memory usage is not
                    balanced (# of news != # of deletes) the test will fail. This is
                    pretty handy.

                    As others have mentioned Refactoring is harder, so spending a little
                    more time with a design vision might help depending on the team design
                    experience. Manage your dependencies. Use forward declarations to
                    avoid includes in your includes. Use interfaces classes as dependency
                    dead ends.

                    I've written a few couple papers on this topic
                    http://www.objectmentor.com/resources/listArticles?key=topic&topic=Embedded%20Software

                    --- In extremeprogramming@yahoogroups.com, Alex Pukinskis
                    <Alex.Pukinskis@...> wrote:
                    >
                    > I am working with a team that is developing telecom applications in C++.
                    > So far, we're doing Scrum with user stories and plan to start adding
                    in the
                    > core XP practices within a few weeks (TDD, Simple Design,
                    Refactoring, Pair
                    > Programming).
                    >
                    > I have taught TDD in other languages (Java, C#, PHP) but never in
                    C++. Any
                    > big gotchas we should watch out for in this context?
                    >
                    > Anyone with some experience doing TDD in C++ willing to talk about their
                    > experiences? Particularly in telecom, networking, or embedded
                    applications?
                    >
                    > Thanks,
                    >
                    > -Alex
                    >
                    > --
                    > Alex Pukinskis - Agile Coach
                    > Rally Software Development - http://rallydev.com/
                    >
                  • Anthony Williams
                    ... I do most of my development in C++, doing TDD, and most of the applications I work on have some networking component. As others have mentioned, the first
                    Message 9 of 27 , Apr 3, 2006
                      Alex Pukinskis <Alex.Pukinskis@...> writes:

                      > Anyone with some experience doing TDD in C++ willing to talk about their
                      > experiences? Particularly in telecom, networking, or embedded applications?

                      I do most of my development in C++, doing TDD, and most of the applications I
                      work on have some networking component.

                      As others have mentioned, the first step is to find/build a unit testing
                      framework. I use a homegrown one for most projects, but I also use Boost.Test
                      for others. I like my homegrown one, because it uses the constructor of the
                      test-case class for setup, and the destructor for tear-down. YMMV.

                      Once you're up and running, again as others have mentioned, pay close
                      attention to build times. Excessive build times can really hurt the TDD cycle,
                      as you have to do something else whilst it's building, otherwise you get
                      bored. The key to getting build times down is to work hard on reducing
                      dependencies. Persistent refactoring also helps --- if there's less code,
                      because there's less duplication, then it takes less time to compile it.

                      For network apps, test the actual network comms once --- to verify that sent
                      data does get sent, and data is received correctly. Once that works, then do
                      everything else one layer removed, working to an interface, with a dummy
                      implementation in the test. That way you can avoid the overhead inherent in
                      network comms, not just in time, but also in test complexity.

                      Of course, as with any development, you want to use good C++ coding
                      conventions and idioms, but the real difference that TDD makes to my C++ code
                      is the extensive use of abstract classes as interfaces.

                      Anthony
                      --
                      Anthony Williams
                      Software Developer
                      Just Software Solutions Ltd
                      http://www.justsoftwaresolutions.co.uk
                    • Alex Pukinskis
                      ... I suspect it might not be necessary, but since several of the developers regard Java as a toy language that s fine for applications but not for real
                      Message 10 of 27 , Apr 3, 2006
                        On 04 02 2006 7:25 AM, "Dean Wampler" <deanwampler@...> wrote:

                        > On a side note, is it necessary to use C++ for this project or perhaps
                        > for most of its subsystems?

                        I suspect it might not be necessary, but since several of the developers
                        regard Java as a "toy" language that's fine for "applications" but not for
                        "real programming", I'm not about to start that battle now. C++ is
                        currently only used for the realtime portion of the application; the GUI
                        portion is being written in .NET, although the team is considering Ruby on
                        Rails as a platform-independent alternative.

                        -Alex
                        --
                        Alex Pukinskis - Agile Coach
                        Rally Software Development - http://rallydev.com/
                      • Aragao, Andre Augusto de (Andre)
                        Very strange indeed. Not the right place for flame warts... But to this point, .NET is the real toy framework (it s not a language, by the way) - at least
                        Message 11 of 27 , Apr 3, 2006
                          Very strange indeed. Not the right place for flame warts... But to this
                          point, .NET is the real "toy" framework (it's not a language, by the
                          way) - at least for some time. I hope you're not integrating C++ using
                          Managed Objects...

                          -----Original Message-----
                          From: extremeprogramming@yahoogroups.com
                          [mailto:extremeprogramming@yahoogroups.com] On Behalf Of Alex Pukinskis
                          Sent: Monday, April 03, 2006 12:12 PM
                          To: extremeprogramming@yahoogroups.com
                          Subject: Re: [XP] TDD and C++




                          On 04 02 2006 7:25 AM, "Dean Wampler" <deanwampler@...> wrote:

                          > On a side note, is it necessary to use C++ for this project or perhaps

                          > for most of its subsystems?

                          I suspect it might not be necessary, but since several of the developers
                          regard Java as a "toy" language that's fine for "applications" but not
                          for "real programming", I'm not about to start that battle now. C++ is
                          currently only used for the realtime portion of the application; the GUI
                          portion is being written in .NET, although the team is considering Ruby
                          on Rails as a platform-independent alternative.

                          -Alex
                          --
                          Alex Pukinskis - Agile Coach
                          Rally Software Development - http://rallydev.com/




                          To Post a message, send it to: extremeprogramming@...

                          To Unsubscribe, send a blank message to:
                          extremeprogramming-unsubscribe@...

                          ad-free courtesy of objectmentor.com
                          Yahoo! Groups Links
                        • Alex Pukinskis
                          Nope, not embedded using a Windows operating system. The only reason I asked for that kind of example is that some of the development team members are highly
                          Message 12 of 27 , Apr 3, 2006
                            Nope, not embedded using a Windows operating system. The only reason I
                            asked for that kind of example is that some of the development team members
                            are highly skeptical of techniques used for "application development" being
                            applicable for "real programming". Embedded examples would be useful
                            because this team would consider that "real programming".

                            This application isn't embedded; it runs on a regular Linux box.

                            -Alex


                            On 04 02 2006 2:24 PM, "Keith Ray" <keith.ray@...> wrote:

                            > The original poster mentioned embedded software, and if they were
                            embedding
                            > using a Windows operating system, I would recommend that
                            they re-think that
                            > decision.

                            > C++ generally goes hand in hand with COM. If this is the case
                            > with
                            > your project reduce the need to test the COM components by using the
                            >
                            > envelope ­ letter pattern to forward all COM calls to a worker class
                            > that
                            > can be tested outside the COM runtime.

                            --

                            C. Keith
                            > Ray
                            <http://homepage.mac.com/keithray/blog/index.html>
                            <http://homepage.mac.co
                            > m/keithray/xpminifaq.html>
                            <http://homepage.mac.com/keithray/resume2.html>


                            T
                            > o Post a message, send it to: extremeprogramming@...

                            To
                            > Unsubscribe, send a blank message to:
                            > extremeprogramming-unsubscribe@...

                            ad-free courtesy of
                            > objectmentor.com
                            Yahoo! Groups Links

                            http://groups.yahoo.com/group/extremeprogramming/


                            > extremeprogramming-unsubscribe@yahoogroups.com

                            http://docs.yahoo.com/info/terms/



                            --
                            Alex Pukinskis - Agile Coach
                            Rally Software Development - http://rallydev.com/
                          • Keith Ray
                            Smalltalk was used decades ago as the real-time embedded code in Textronics device (an oscilliscope, I think.) But I don t seriously expect you to consider it,
                            Message 13 of 27 , Apr 3, 2006
                              Smalltalk was used decades ago as the real-time embedded code in
                              Textronics device (an oscilliscope, I think.) But I don't seriously
                              expect you to consider it, even though one or more cell-phone
                              companies might be using it today.

                              http://www.incuba.dk/sw1064.asp

                              http://www.cincomsmalltalk.com/blog/blogView?showComments=true&entry=3261222720


                              On 4/3/06, Alex Pukinskis <Alex.Pukinskis@...> wrote:
                              > Nope, not embedded using a Windows operating system. The only reason I
                              > asked for that kind of example is that some of the development team members
                              > are highly skeptical of techniques used for "application development" being
                              > applicable for "real programming". Embedded examples would be useful
                              > because this team would consider that "real programming".
                              >
                              > This application isn't embedded; it runs on a regular Linux box.
                              >
                              > -Alex
                              >
                              >
                              > On 04 02 2006 2:24 PM, "Keith Ray" <keith.ray@...> wrote:
                              >
                              > > The original poster mentioned embedded software, and if they were
                              > embedding
                              > > using a Windows operating system, I would recommend that
                              > they re-think that
                              > > decision.
                              >
                              > > C++ generally goes hand in hand with COM. If this is the case
                              > > with
                              > > your project reduce the need to test the COM components by using the
                              > >
                              > > envelope ­ letter pattern to forward all COM calls to a worker class
                              > > that
                              > > can be tested outside the COM runtime.
                              >
                              > --
                              >
                              > C. Keith
                              > > Ray
                              > <http://homepage.mac.com/keithray/blog/index.html>
                              > <http://homepage.mac.co
                              > > m/keithray/xpminifaq.html>
                              > <http://homepage.mac.com/keithray/resume2.html>
                              >
                              >
                              > T
                              > > o Post a message, send it to: extremeprogramming@...
                              >
                              > To
                              > > Unsubscribe, send a blank message to:
                              > > extremeprogramming-unsubscribe@...
                              >
                              > ad-free courtesy of
                              > > objectmentor.com
                              > Yahoo! Groups Links
                              >
                              > http://groups.yahoo.com/group/extremeprogramming/
                              >
                              >
                              > > extremeprogramming-unsubscribe@yahoogroups.com
                              >
                              > http://docs.yahoo.com/info/terms/
                              >
                              >
                              >
                              > --
                              > Alex Pukinskis - Agile Coach
                              > Rally Software Development - http://rallydev.com/
                              >
                              >
                              >
                              >
                              > To Post a message, send it to: extremeprogramming@...
                              >
                              > To Unsubscribe, send a blank message to: extremeprogramming-unsubscribe@...
                              >
                              > ad-free courtesy of objectmentor.com
                              > Yahoo! Groups Links
                              >
                              >
                              >
                              >
                              >
                              >
                              >


                              --

                              C. Keith Ray
                              <http://homepage.mac.com/keithray/blog/index.html>
                              <http://homepage.mac.com/keithray/xpminifaq.html>
                              <http://homepage.mac.com/keithray/resume2.html>
                            • Ian Collins
                              ... If you are developing on Linux, invest in a decent build server. I d recommend a dual dual-core Opteron with plenty of RAM. This will go a long way to
                              Message 14 of 27 , Apr 3, 2006
                                Alex Pukinskis wrote:

                                >Nope, not embedded using a Windows operating system. The only reason I
                                >asked for that kind of example is that some of the development team members
                                >are highly skeptical of techniques used for "application development" being
                                >applicable for "real programming". Embedded examples would be useful
                                >because this team would consider that "real programming".
                                >
                                >This application isn't embedded; it runs on a regular Linux box.
                                >
                                >
                                >
                                If you are developing on Linux, invest in a decent build server. I'd
                                recommend a dual dual-core Opteron with plenty of RAM. This will go a
                                long way to keeping your build times down.

                                Ian
                              • Keith Braithwaite
                                ... Hi Alex. You might find http://www.keithbraithwaite.demon.co.uk/professional/presentations/index.html#embedded useful, it describes two sets of experience
                                Message 15 of 27 , Apr 4, 2006
                                  --- In extremeprogramming@yahoogroups.com, Ian Collins <ian@...> wrote:
                                  >
                                  > Alex Pukinskis wrote:
                                  >
                                  >Anyone with some experience doing TDD in C++ willing to talk about their
                                  >experiences?
                                  >Particularly in telecom, networking, or embedded applications?
                                  Hi Alex. You might find
                                  http://www.keithbraithwaite.demon.co.uk/professional/presentations/index.html#embedded
                                  useful, it describes two sets of experience with exactly that sort of
                                  thing.

                                  >
                                  > Make sure you can keep your build times short, we drifted up to a couple
                                  > of minutes for a full build, a bit too long in my opinion, 30 seconds is
                                  > a better target to aim for.
                                  Yes. We suffered with this a bit at Penrillian. Most of the work done
                                  when I was there was targeted on various Symbian devices, and what
                                  with the rather clunky toolchain builds were often excessively long.
                                  (in the case of some firmware extentions we did, several hours for a
                                  full build and complete regression test!)

                                  > If you can, do all of your development and testing off the target.
                                  I'd certainly aim to do as much testing as possible off the target.
                                  There again, emulatiors aren't perfect. We found many problems with
                                  connectivity between certain handsets and certain Bluetooth devices,
                                  for instance--the emulator can't have the same hardware drivers in it
                                  as the deployment platform and sometimes that matters. We ended up
                                  deriving http://www.symbianosunit.co.uk/ from cxxunit to help with
                                  on-device testing.

                                  Keith
                                • Jason Almeter
                                  ... Interesting. I ve been tinkering with my cxxUnit this week (merging a version that escaped to another platform back with the original.) I used the jUnit
                                  Message 16 of 27 , Apr 7, 2006
                                    David Carlton <carlton@...> writes:
                                    >
                                    > The main mistake I made was not initially using RAII to set up and
                                    > tear down tests. Have each test correspond to a class, and set things
                                    > up so the class instance doesn't get constructed until you're about to
                                    > run it and the destructor gets called right after you run it. This
                                    > works a lot better than jUnit-style setUp and tearDown methods.

                                    Interesting. I've been tinkering with my cxxUnit this week (merging a
                                    version that escaped to another platform back with the original.) I
                                    used the jUnit style setup and teardown. I'll need to see what RAII
                                    would do to my implementation. Actually changing it might not happen,
                                    though. There are a few hundred of them around these days.

                                    -Jason

                                    --

                                    jalmeter under 99 at yahoo
                                  • David Carlton
                                    ... The longer you wait, the more there will be. :-) By the time I got around to make that change, there were thousands of tests (though certainly not
                                    Message 17 of 27 , Apr 7, 2006
                                      On Fri, 07 Apr 2006 19:48:01 -0400, Jason Almeter <jalmeter_99@...> said:
                                      > David Carlton <carlton@...> writes:

                                      >> The main mistake I made was not initially using RAII to set up and
                                      >> tear down tests. Have each test correspond to a class, and set things
                                      >> up so the class instance doesn't get constructed until you're about to
                                      >> run it and the destructor gets called right after you run it. This
                                      >> works a lot better than jUnit-style setUp and tearDown methods.

                                      > Interesting. I've been tinkering with my cxxUnit this week (merging a
                                      > version that escaped to another platform back with the original.) I
                                      > used the jUnit style setup and teardown. I'll need to see what RAII
                                      > would do to my implementation. Actually changing it might not happen,
                                      > though. There are a few hundred of them around these days.

                                      The longer you wait, the more there will be. :-) By the time I got
                                      around to make that change, there were thousands of tests (though
                                      certainly not thousands of setUp methods), but it was definitely worth
                                      it. Advantages:

                                      * The tests are shorter.

                                      * The tests are more like idiomatic C++, so they reinforce your good
                                      habits.

                                      * It makes it a lot easier to modify a test's setup/teardown to add
                                      extra functionality from the default. Otherwise, people would tend
                                      to get lazy and stick that extra functionality in the body of the
                                      test; you can get away with that for setup, but for teardown it
                                      means that it's easy for a failure to leave your system in a bad
                                      state, leading to cascade failures.

                                      * You can write easily write mixin test helper classes that provide
                                      some extra checking functionality but that require setup/teardown of
                                      their own: just write the class, inherit from it in addition to
                                      whatever else you'd inherit from, and you're all set!

                                      And it's easy to refactor to this state: the old abstract test base
                                      class with virtual setUp and tearDown methods is still there, it's
                                      just that nobody inherits from it any more.

                                      David Carlton
                                      carlton@...
                                    • Philippe AMELINE
                                      ... Hi, This point really seems of interest, but the way you describe it is too technical to be plainly understandable for me... and probably for some others
                                      Message 18 of 27 , Apr 8, 2006
                                        David Carlton a écrit :

                                        >On Fri, 07 Apr 2006 19:48:01 -0400, Jason Almeter <jalmeter_99@...> said:
                                        >
                                        >
                                        >>David Carlton <carlton@...> writes:
                                        >>
                                        >>
                                        >
                                        >
                                        >
                                        >>>The main mistake I made was not initially using RAII to set up and
                                        >>>tear down tests. Have each test correspond to a class, and set things
                                        >>>up so the class instance doesn't get constructed until you're about to
                                        >>>run it and the destructor gets called right after you run it. This
                                        >>>works a lot better than jUnit-style setUp and tearDown methods.
                                        >>>
                                        >>>
                                        >
                                        >
                                        >
                                        >>Interesting. I've been tinkering with my cxxUnit this week (merging a
                                        >>version that escaped to another platform back with the original.) I
                                        >>used the jUnit style setup and teardown. I'll need to see what RAII
                                        >>would do to my implementation. Actually changing it might not happen,
                                        >>though. There are a few hundred of them around these days.
                                        >>
                                        >>
                                        >
                                        >The longer you wait, the more there will be. :-) By the time I got
                                        >around to make that change, there were thousands of tests (though
                                        >certainly not thousands of setUp methods), but it was definitely worth
                                        >it. Advantages:
                                        >
                                        >* The tests are shorter.
                                        >
                                        >* The tests are more like idiomatic C++, so they reinforce your good
                                        > habits.
                                        >
                                        >* It makes it a lot easier to modify a test's setup/teardown to add
                                        > extra functionality from the default. Otherwise, people would tend
                                        > to get lazy and stick that extra functionality in the body of the
                                        > test; you can get away with that for setup, but for teardown it
                                        > means that it's easy for a failure to leave your system in a bad
                                        > state, leading to cascade failures.
                                        >
                                        >* You can write easily write mixin test helper classes that provide
                                        > some extra checking functionality but that require setup/teardown of
                                        > their own: just write the class, inherit from it in addition to
                                        > whatever else you'd inherit from, and you're all set!
                                        >
                                        >And it's easy to refactor to this state: the old abstract test base
                                        >class with virtual setUp and tearDown methods is still there, it's
                                        >just that nobody inherits from it any more.
                                        >
                                        >David Carlton
                                        >carlton@...
                                        >
                                        >
                                        >
                                        Hi,

                                        This point really seems of interest, but the way you describe it is too
                                        technical to be plainly understandable for me... and probably for some
                                        others ;-)
                                        Can you illustrate what you say by some simple examples... or point out
                                        some references?

                                        Thanks

                                        Philippe
                                      • David Carlton
                                        ... [ advantages for using constructor/destructor in place of setUp/tearDown deleted ] [ other miscellaneous comments deleted ] ... I m happy to talk about
                                        Message 19 of 27 , Apr 8, 2006
                                          On Sat, 08 Apr 2006 16:50:04 +0200, Philippe AMELINE <philippe.ameline@...> said:
                                          > David Carlton a écrit :

                                          [ advantages for using constructor/destructor in place of
                                          setUp/tearDown deleted ]

                                          [ other miscellaneous comments deleted ]

                                          > This point really seems of interest, but the way you describe it is
                                          > too technical to be plainly understandable for me... and probably
                                          > for some others ;-)

                                          > Can you illustrate what you say by some simple examples... or point
                                          > out some references?

                                          I'm happy to talk about this at length - just tell me what you want me
                                          to talk about. Do you want me to talk about the advantages of doing
                                          things in the way I recommend, how to implement it, or something else?

                                          If the implementation is the question, here's a sketch of how I
                                          refactored from the old way of doing things to the new way of doing
                                          things.

                                          WARNING: I am typing this code off of the top of my head; I would be
                                          shocked if I didn't make a typo somewhere. I hope the ideas are
                                          there, though.

                                          In the old version, I had classes like this:

                                          class Test {
                                          public:
                                          virtual void setUp() {}

                                          virtual void run() = 0;

                                          virtual void tearDown() = 0;
                                          };

                                          class Suite : public Test {
                                          public:
                                          void run(); // sets up, runs, tears down all tests in list

                                          void addTest(Test *test); // adds a test to the list

                                          private:
                                          std::list<Test *> tests_;
                                          };


                                          This might be used as follows:

                                          class StackBase : public Test {
                                          public:
                                          void setUp() { stack_ = new Stack(); }

                                          void tearDown() { delete stack_; }

                                          protected:
                                          Stack &stack() { return *stack_; }

                                          private:
                                          Stack *stack_;
                                          };

                                          class PushPop : public StackBase {
                                          public:
                                          void run() {
                                          ASSERT(stack().empty());

                                          stack().push(1);

                                          ASSERT(!stack().empy());
                                          ASSERT_EQUAL(1, stack().pop());

                                          ASSERT(stack().empty());
                                          }
                                          };

                                          // Other stack tests go here.

                                          class StackSuite : public Suite {
                                          public:
                                          void setUp() {
                                          newTest(new PushPop())
                                          // Add other stack tests here.
                                          }
                                          };


                                          Which is fine (and we did things this way for maybe a couple of
                                          years), but it has its limitations. For example, if the individual
                                          tests want to add more setup/teardown functionality, it's easy to
                                          forget to call the base class's setup/teardown, or to call it in the
                                          wrong place.

                                          So we added the following:

                                          template<typename T>
                                          class TestHolder : public Test {
                                          public
                                          void setUp() { test_ = new T(); }

                                          void run() { test_->run(); }

                                          void tearDown() { delete test_; }
                                          };

                                          And we added another addTest() method to Suite:

                                          class Suite {
                                          public:
                                          // Rest as above.

                                          template<typename T>
                                          void addTest() {
                                          addTest(new TestHolder<T>);
                                          }
                                          };

                                          Then our earlier StackBase example turns into this:

                                          class StackBase {
                                          protected:
                                          Stack &stack() { return stack_; }

                                          private:
                                          Stack stack_;
                                          };

                                          No need for explicit setUp/tearDown at all: the compiler generated
                                          default constructor/destructor do our job for us. (It's also not
                                          unusual for setUp to be replaced by a short constructor that we have
                                          to write, and for tearDown to vanish.)

                                          And StackSuite just does

                                          addTest<PushPop>();

                                          instead of

                                          addTest(new PushPop());

                                          Which is no harder (or easier) than the other version.


                                          Is this useful? Please tell me areas where you'd like elaboration
                                          (either here or in my earlier e-mail), and I'll be happy to say more.

                                          David Carlton
                                          carlton@...
                                        • Philippe AMELINE
                                          ... Thank you David, From what I understand, the main advantage is to have the setup function incorporated in the constructor and the tear down function in the
                                          Message 20 of 27 , Apr 8, 2006
                                            David Carlton a écrit :

                                            >On Sat, 08 Apr 2006 16:50:04 +0200, Philippe AMELINE <philippe.ameline@...> said:
                                            >
                                            >
                                            >>David Carlton a écrit :
                                            >>
                                            >>
                                            >
                                            >[ advantages for using constructor/destructor in place of
                                            >setUp/tearDown deleted ]
                                            >
                                            >[ other miscellaneous comments deleted ]
                                            >
                                            >
                                            >
                                            >>This point really seems of interest, but the way you describe it is
                                            >>too technical to be plainly understandable for me... and probably
                                            >>for some others ;-)
                                            >>
                                            >>
                                            >
                                            >
                                            >
                                            >>Can you illustrate what you say by some simple examples... or point
                                            >>out some references?
                                            >>
                                            >>
                                            >
                                            >I'm happy to talk about this at length - just tell me what you want me
                                            >to talk about. Do you want me to talk about the advantages of doing
                                            >things in the way I recommend, how to implement it, or something else?
                                            >
                                            >If the implementation is the question, here's a sketch of how I
                                            >refactored from the old way of doing things to the new way of doing
                                            >things.
                                            >
                                            >WARNING: I am typing this code off of the top of my head; I would be
                                            >shocked if I didn't make a typo somewhere. I hope the ideas are
                                            >there, though.
                                            >
                                            >In the old version, I had classes like this:
                                            >
                                            > class Test {
                                            > public:
                                            > virtual void setUp() {}
                                            >
                                            > virtual void run() = 0;
                                            >
                                            > virtual void tearDown() = 0;
                                            > };
                                            >
                                            > class Suite : public Test {
                                            > public:
                                            > void run(); // sets up, runs, tears down all tests in list
                                            >
                                            > void addTest(Test *test); // adds a test to the list
                                            >
                                            > private:
                                            > std::list<Test *> tests_;
                                            > };
                                            >
                                            >
                                            >This might be used as follows:
                                            >
                                            > class StackBase : public Test {
                                            > public:
                                            > void setUp() { stack_ = new Stack(); }
                                            >
                                            > void tearDown() { delete stack_; }
                                            >
                                            > protected:
                                            > Stack &stack() { return *stack_; }
                                            >
                                            > private:
                                            > Stack *stack_;
                                            > };
                                            >
                                            > class PushPop : public StackBase {
                                            > public:
                                            > void run() {
                                            > ASSERT(stack().empty());
                                            >
                                            > stack().push(1);
                                            >
                                            > ASSERT(!stack().empy());
                                            > ASSERT_EQUAL(1, stack().pop());
                                            >
                                            > ASSERT(stack().empty());
                                            > }
                                            > };
                                            >
                                            > // Other stack tests go here.
                                            >
                                            > class StackSuite : public Suite {
                                            > public:
                                            > void setUp() {
                                            > newTest(new PushPop())
                                            > // Add other stack tests here.
                                            > }
                                            > };
                                            >
                                            >
                                            >Which is fine (and we did things this way for maybe a couple of
                                            >years), but it has its limitations. For example, if the individual
                                            >tests want to add more setup/teardown functionality, it's easy to
                                            >forget to call the base class's setup/teardown, or to call it in the
                                            >wrong place.
                                            >
                                            >So we added the following:
                                            >
                                            > template<typename T>
                                            > class TestHolder : public Test {
                                            > public
                                            > void setUp() { test_ = new T(); }
                                            >
                                            > void run() { test_->run(); }
                                            >
                                            > void tearDown() { delete test_; }
                                            > };
                                            >
                                            >And we added another addTest() method to Suite:
                                            >
                                            > class Suite {
                                            > public:
                                            > // Rest as above.
                                            >
                                            > template<typename T>
                                            > void addTest() {
                                            > addTest(new TestHolder<T>);
                                            > }
                                            > };
                                            >
                                            >Then our earlier StackBase example turns into this:
                                            >
                                            > class StackBase {
                                            > protected:
                                            > Stack &stack() { return stack_; }
                                            >
                                            > private:
                                            > Stack stack_;
                                            > };
                                            >
                                            >No need for explicit setUp/tearDown at all: the compiler generated
                                            >default constructor/destructor do our job for us. (It's also not
                                            >unusual for setUp to be replaced by a short constructor that we have
                                            >to write, and for tearDown to vanish.)
                                            >
                                            >And StackSuite just does
                                            >
                                            > addTest<PushPop>();
                                            >
                                            >instead of
                                            >
                                            > addTest(new PushPop());
                                            >
                                            >Which is no harder (or easier) than the other version.
                                            >
                                            >
                                            >Is this useful? Please tell me areas where you'd like elaboration
                                            >(either here or in my earlier e-mail), and I'll be happy to say more.
                                            >
                                            >
                                            Thank you David,

                                            From what I understand, the main advantage is to have the setup
                                            function incorporated in the constructor and the tear down function in
                                            the destructor.
                                            Then the object has just to be created and deleted at the proper time.

                                            You are also making use of templates to make this behavior generic.

                                            Nice use of C++ capabilities.
                                            Can you share the base code, so we can play with it (and maybe collaborate)?

                                            Philippe
                                          • David Carlton
                                            ... Exactly. RAII (Resource Allocation Is Initialization) is (by far, I think) the most important C++-specific design pattern, so your test framework should
                                            Message 21 of 27 , Apr 8, 2006
                                              On Sat, 08 Apr 2006 21:13:25 +0200, Philippe AMELINE <philippe.ameline@...> said:

                                              > From what I understand, the main advantage is to have the setup
                                              > function incorporated in the constructor and the tear down function in
                                              > the destructor.
                                              > Then the object has just to be created and deleted at the proper time.

                                              Exactly. RAII (Resource Allocation Is Initialization) is (by far, I
                                              think) the most important C++-specific design pattern, so your test
                                              framework should reflect that!

                                              > Can you share the base code, so we can play with it (and maybe
                                              > collaborate)?

                                              I'll work on it, but it might take a while to get permission...

                                              David Carlton
                                              carlton@...
                                            • Ian Collins
                                              ... Thanks for an informative post. I d never considered wrapping tests this way, but I will in future. The relationship between test constructors and
                                              Message 22 of 27 , Apr 8, 2006
                                                David Carlton wrote:

                                                >I'm happy to talk about this at length - just tell me what you want me
                                                >to talk about. Do you want me to talk about the advantages of doing
                                                >things in the way I recommend, how to implement it, or something else?
                                                >
                                                >If the implementation is the question, here's a sketch of how I
                                                >refactored from the old way of doing things to the new way of doing
                                                >things.
                                                >
                                                >
                                                >
                                                Thanks for an informative post. I'd never considered wrapping tests
                                                this way, but I will in future. The relationship between test
                                                constructors and setUp() is something I've never been happy with in cppUnit.

                                                Cheers,

                                                Ian.
                                              Your message has been successfully submitted and would be delivered to recipients shortly.