Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Unit testing in Qt seems too hard
QtWS25 Last Chance

Unit testing in Qt seems too hard

Scheduled Pinned Locked Moved Unsolved General and Desktop
11 Posts 5 Posters 1.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • R Offline
    R Offline
    rico-chet
    wrote on last edited by rico-chet
    #1

    When trying to unit-test code written with Qt classes (mainly core), I often find it too hard to unit-test because it's not easy to replace production code with test code (test doubles/fakes/mocks).

    Canonically, behavior replacement and sensing is done via interfaces. In his famous book Working Effectively with Legacy Code, Michael Feathers writes (pp. 280-281):

    In other cases, classes are concrete and declared final or sealed, or they have key functions that are non-virtual, leaving no way to fake them out under test. In these cases, sometimes the best thing you can do is write a thin wrapper over the classes that you need to separate out. Make sure that you write your vendor and give them grief about making your development work difficult.
    

    Take e.g. a QFile, it has no interface to depend on, and many of its methods aren't virtual. So we're left with lot of work to get it faked or mocked, and it's a burden to maintain. We'd sometimes use duck typing with templates, but again it's not a great experience, especially without C++ Concepts at hand yet. Also, we end up doing more coarse-grained testing which isn't a great source of feedback.

    So, now that the Qt Company seems to increase investment into easier testing, can we expect any improvements at this point? We're paying customers, by the way.

    JonBJ 1 Reply Last reply
    0
    • R rico-chet

      When trying to unit-test code written with Qt classes (mainly core), I often find it too hard to unit-test because it's not easy to replace production code with test code (test doubles/fakes/mocks).

      Canonically, behavior replacement and sensing is done via interfaces. In his famous book Working Effectively with Legacy Code, Michael Feathers writes (pp. 280-281):

      In other cases, classes are concrete and declared final or sealed, or they have key functions that are non-virtual, leaving no way to fake them out under test. In these cases, sometimes the best thing you can do is write a thin wrapper over the classes that you need to separate out. Make sure that you write your vendor and give them grief about making your development work difficult.
      

      Take e.g. a QFile, it has no interface to depend on, and many of its methods aren't virtual. So we're left with lot of work to get it faked or mocked, and it's a burden to maintain. We'd sometimes use duck typing with templates, but again it's not a great experience, especially without C++ Concepts at hand yet. Also, we end up doing more coarse-grained testing which isn't a great source of feedback.

      So, now that the Qt Company seems to increase investment into easier testing, can we expect any improvements at this point? We're paying customers, by the way.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @rico-chet
      Hi. This is a user forum, users just like you.

      can we expect any improvements at this point? We're paying customers, by the way.

      If you are paying you should take this up with The Qt Company!

      R 1 Reply Last reply
      1
      • SGaistS Offline
        SGaistS Offline
        SGaist
        Lifetime Qt Champion
        wrote on last edited by
        #3

        Hi,

        QFile is a good example, if you want to mock a file then your interface should handle a QIODevice rather than specifically a QFile. Doing so you can replace it with a mock class that implements whatever you want for the tests.

        Interested in AI ? www.idiap.ch
        Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

        1 Reply Last reply
        5
        • JonBJ JonB

          @rico-chet
          Hi. This is a user forum, users just like you.

          can we expect any improvements at this point? We're paying customers, by the way.

          If you are paying you should take this up with The Qt Company!

          R Offline
          R Offline
          rico-chet
          wrote on last edited by rico-chet
          #4

          @JonB so the Qt Company doesn't care about the user voices here? Not the greatest attitude to me... I will try to bring this up through our support channel.

          @SGaist Let's take QFile, it has its own methods like remove() which cannot be replaced via its base class. It cannot be replaced by a derived class either, as it's not virtual. Same goes for QIODevice::read() which isn't virtual and cannot be replaced easily.

          jsulmJ 1 Reply Last reply
          0
          • R rico-chet

            @JonB so the Qt Company doesn't care about the user voices here? Not the greatest attitude to me... I will try to bring this up through our support channel.

            @SGaist Let's take QFile, it has its own methods like remove() which cannot be replaced via its base class. It cannot be replaced by a derived class either, as it's not virtual. Same goes for QIODevice::read() which isn't virtual and cannot be replaced easily.

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on last edited by
            #5

            @rico-chet said in Unit testing in Qt seems too hard:

            so the Qt Company doesn't care about the user voices here?

            As paying user you can ask QtCompany directly. This here is user forum, most of the people here do not work for QtCompany.
            Also, if you have any improvement suggestions then file a change request in Qt bug tracker

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @rico-chet said in Unit testing in Qt seems too hard:

              @SGaist Let's take QFile, it has its own methods like remove() which cannot be replaced via its base class. It cannot be replaced by a derived class either, as it's not virtual. Same goes for QIODevice::read() which isn't virtual and cannot be replaced easily.

              For QIODevice, you are looking at the wrong function, there's QIODevice::readData for you to re-implement.

              For QFile, if you need to replace the remove function with something else, then I would argue that you are not using the correct abstraction level. Not knowing anything about what you are currently implementing, it's impossible to discuss what would be best. In any case, making every method of a class virtual is usually not the solution. In the remove example, needing to re-implement it to perform some other task than removing would both feel counter-intuitive and dangerous. If you need to do something different, you might rather want to add a new method to do what you want or implement a wrapper class that provides the API you need on top of QFile.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              R 1 Reply Last reply
              1
              • SGaistS SGaist

                @rico-chet said in Unit testing in Qt seems too hard:

                @SGaist Let's take QFile, it has its own methods like remove() which cannot be replaced via its base class. It cannot be replaced by a derived class either, as it's not virtual. Same goes for QIODevice::read() which isn't virtual and cannot be replaced easily.

                For QIODevice, you are looking at the wrong function, there's QIODevice::readData for you to re-implement.

                For QFile, if you need to replace the remove function with something else, then I would argue that you are not using the correct abstraction level. Not knowing anything about what you are currently implementing, it's impossible to discuss what would be best. In any case, making every method of a class virtual is usually not the solution. In the remove example, needing to re-implement it to perform some other task than removing would both feel counter-intuitive and dangerous. If you need to do something different, you might rather want to add a new method to do what you want or implement a wrapper class that provides the API you need on top of QFile.

                R Offline
                R Offline
                rico-chet
                wrote on last edited by
                #7

                @SGaist said in Unit testing in Qt seems too hard:

                For QIODevice, you are looking at the wrong function, there's QIODevice::readData for you to re-implement.

                There's no guarantee that QIODevice::readAll calls QIODevice::readData, it's not part of its contract. Also, testing through the QFile implementation isn't unit testing, as a red test can have multiple reasons to fail (the unit under test or the QFile implementation)

                For QFile, if you need to replace the remove function with something else, then I would argue that you are not using the correct abstraction level.

                I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                [...] implement a wrapper class that provides the API you need on top of QFile.

                I believe this work should be performed at the Qt Company, not by their users or customers. I asked our internal contact to file a request.

                VRoninV SGaistS 2 Replies Last reply
                0
                • R rico-chet

                  @SGaist said in Unit testing in Qt seems too hard:

                  For QIODevice, you are looking at the wrong function, there's QIODevice::readData for you to re-implement.

                  There's no guarantee that QIODevice::readAll calls QIODevice::readData, it's not part of its contract. Also, testing through the QFile implementation isn't unit testing, as a red test can have multiple reasons to fail (the unit under test or the QFile implementation)

                  For QFile, if you need to replace the remove function with something else, then I would argue that you are not using the correct abstraction level.

                  I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                  [...] implement a wrapper class that provides the API you need on top of QFile.

                  I believe this work should be performed at the Qt Company, not by their users or customers. I asked our internal contact to file a request.

                  VRoninV Offline
                  VRoninV Offline
                  VRonin
                  wrote on last edited by
                  #8

                  @rico-chet said in Unit testing in Qt seems too hard:

                  I believe this work should be performed at the Qt Company, not by their users or customers. I asked our internal contact to file a request.

                  This forum is first line of defence for users, the mailing list has a lot more participation from TQC and other key external figures in the Qt development ecosystem.

                  "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                  ~Napoleon Bonaparte

                  On a crusade to banish setIndexWidget() from the holy land of Qt

                  R 1 Reply Last reply
                  1
                  • R rico-chet

                    @SGaist said in Unit testing in Qt seems too hard:

                    For QIODevice, you are looking at the wrong function, there's QIODevice::readData for you to re-implement.

                    There's no guarantee that QIODevice::readAll calls QIODevice::readData, it's not part of its contract. Also, testing through the QFile implementation isn't unit testing, as a red test can have multiple reasons to fail (the unit under test or the QFile implementation)

                    For QFile, if you need to replace the remove function with something else, then I would argue that you are not using the correct abstraction level.

                    I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                    [...] implement a wrapper class that provides the API you need on top of QFile.

                    I believe this work should be performed at the Qt Company, not by their users or customers. I asked our internal contact to file a request.

                    SGaistS Offline
                    SGaistS Offline
                    SGaist
                    Lifetime Qt Champion
                    wrote on last edited by
                    #9

                    @rico-chet said in Unit testing in Qt seems too hard:

                    There's no guarantee that QIODevice::readAll calls QIODevice::readData, it's not part of its contract.

                    Take a look at the implementation, the contract of the class is that all methods that do some sort of reading will call in the end readData. It would not make sense to provide this protected method and its write counterPart to ignore them.

                    @rico-chet said in Unit testing in Qt seems too hard:

                    I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                    Then, I'll stand on my point: you are doing something off with your tests. There's no reasons to modify QFile in order to check whether the removal succeeded under the right conditions. You would need tests for both normal cases and what is expected to know normal failure cases.

                    Interested in AI ? www.idiap.ch
                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                    R 1 Reply Last reply
                    2
                    • VRoninV VRonin

                      @rico-chet said in Unit testing in Qt seems too hard:

                      I believe this work should be performed at the Qt Company, not by their users or customers. I asked our internal contact to file a request.

                      This forum is first line of defence for users, the mailing list has a lot more participation from TQC and other key external figures in the Qt development ecosystem.

                      R Offline
                      R Offline
                      rico-chet
                      wrote on last edited by
                      #10

                      @VRonin oh the old trusty mailing lists... Communicating to the TQC through our contact now, got an incident opened.

                      1 Reply Last reply
                      0
                      • SGaistS SGaist

                        @rico-chet said in Unit testing in Qt seems too hard:

                        There's no guarantee that QIODevice::readAll calls QIODevice::readData, it's not part of its contract.

                        Take a look at the implementation, the contract of the class is that all methods that do some sort of reading will call in the end readData. It would not make sense to provide this protected method and its write counterPart to ignore them.

                        @rico-chet said in Unit testing in Qt seems too hard:

                        I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                        Then, I'll stand on my point: you are doing something off with your tests. There's no reasons to modify QFile in order to check whether the removal succeeded under the right conditions. You would need tests for both normal cases and what is expected to know normal failure cases.

                        R Offline
                        R Offline
                        rico-chet
                        wrote on last edited by
                        #11

                        @SGaist said in Unit testing in Qt seems too hard:

                        Take a look at the implementation

                        Software development rule #1: don't depend on unstable things. Implementation details are among the least stable things. I don't have time to go over Qt sources every time we update to a new version to check if the old assumptions still hold, sorry.

                        @rico-chet said in Unit testing in Qt seems too hard:

                        I need to replace the function for sensing during unit testing, e.g. to check that the code under test removes a file under certain conditions only.

                        Then, I'll stand on my point: you are doing something off with your tests. There's no reasons to modify QFile in order to check whether the removal succeeded under the right conditions.

                        To be more precise, I need to replace the function for sensing during unit testing, e.g. to check that the code under test attempts to remove a file under certain conditions only. I don't care so much about failure cases, yet.

                        Replacing behavior of collaborating objects (in our case a QFile) with test doubles is exactly the precondition for small-grained and quick unit testing.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved