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

Re: [XP] TDD and C++

Expand Messages
  • 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 1 of 27 , Apr 2, 2006
    • 0 Attachment
      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
    • Ian Collins
      ... That s an odd generalisation! Ian
      Message 2 of 27 , Apr 2, 2006
      • 0 Attachment
        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 3 of 27 , Apr 2, 2006
        • 0 Attachment
          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 4 of 27 , Apr 2, 2006
          • 0 Attachment
            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 5 of 27 , Apr 2, 2006
            • 0 Attachment
              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 6 of 27 , Apr 3, 2006
              • 0 Attachment
                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 7 of 27 , Apr 3, 2006
                • 0 Attachment
                  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 8 of 27 , Apr 3, 2006
                  • 0 Attachment
                    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 9 of 27 , Apr 3, 2006
                    • 0 Attachment
                      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 10 of 27 , Apr 3, 2006
                      • 0 Attachment
                        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 11 of 27 , Apr 3, 2006
                        • 0 Attachment
                          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 12 of 27 , Apr 3, 2006
                          • 0 Attachment
                            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 13 of 27 , Apr 4, 2006
                            • 0 Attachment
                              --- 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 14 of 27 , Apr 7, 2006
                              • 0 Attachment
                                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 15 of 27 , Apr 7, 2006
                                • 0 Attachment
                                  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 16 of 27 , Apr 8, 2006
                                  • 0 Attachment
                                    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 17 of 27 , Apr 8, 2006
                                    • 0 Attachment
                                      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 18 of 27 , Apr 8, 2006
                                      • 0 Attachment
                                        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 19 of 27 , Apr 8, 2006
                                        • 0 Attachment
                                          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 20 of 27 , Apr 8, 2006
                                          • 0 Attachment
                                            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.