对不适合作为新类提取的私有方法进行单元测试的好方法是什么?

时间:2017-06-16 10:01:24

标签: c++ unit-testing design-patterns tdd

粗略地说,我有一个实现只有一个公共方法run的线程的类。该方法进入一个循环,就像调度程序一个接一个地处理网络消息;如下:

class WorkerThread {

  public:

    void run() {
      while (!b_shutdown) {
        message = getNextMessage();
        switch(message.type) {
          case WRITE:
            write();
          case READ:
            read();
          // ...
          // more cases to handle
        }
      }
    }


  private:

    void write() { /* logic to test */ }
    void read() { /* logic to test */ }
    // more private methods with logic that needs testing

    // some member variables
};

所以重点是我真的不想

  1. 将私有方法提取到另一个类,因为在语义上它们是WorkerThread的一部分。
  2. 将这些方法设为公开,因为它们不会在课堂外的任何地方使用。
  3. 跳过测试,因为它是那些实现主逻辑的方法。
  4. 但是如何优雅地测试私有方法?

    注意:

    1. 可能需要更多公共方法来处理线程的启动和终止,但这不是问题。
    2. 我认为此问题不仅限于c++,因此我使用更受欢迎的静态类型Java标记它以获得更多关注:P

2 个答案:

答案 0 :(得分:10)

简单地说:不要。测试公共接口,没有别的。最重要的是,这是唯一重要的事情。

如果你想看看它是否正常工作,应该通过<div class="columns"> <ul class="price"> <li class="header">Hard Drive Format</li> <li class="grey">£10</li> <li>Format Hard Drive</li> <li>Removes ALL Files From Drive</li> <li>Fresh Install Windows</li> <li class="grey"> <button onclick="document.getElementById('id01').style.display='block'">Sign Up</button> </li> </ul> </div> <!-- The Modal (contains the Sign Up form) --> <div class="modal" id="id01"> <span class="close" onclick="document.getElementById('id01').style.display='none'" title="Close Modal">&times;</span> <div class="container modal-content"> <div class="row"> <!-- You can make it whatever width you want. I'm making it full width on <= small devices and 4/12 page width on >= medium devices --> <div class="col-xs-12 col-md-4"> <!-- CREDIT CARD FORM STARTS HERE --> <div class="panel panel-default credit-card-box"> <div class="panel-heading display-table"> <div class="row display-tr"> <h3 class="panel-title display-td">Payment Details</h3> <div class="display-td"><img class="img-responsive pull-right" src="http://i76.imgup.net/accepted_c22e0.png"></div> </div> </div> <div class="panel-body"> <form id="payment-form" name="payment-form" role="form"> <div class="row"> <div class="col-xs-12"> <div class="form-group"> <label for="cardNumber">CARD NUMBER</label> <div class="input-group"> <input autocomplete="cc-number" autofocus="" class="form-control" name="cardNumber" placeholder="Valid Card Number" required="" type="tel"> <span class="input-group-addon"><i class="fa fa-credit-card"></i></span> </div> </div> </div> </div> <div class="row"> <div class="col-xs-7 col-md-7"> <div class="form-group"> <label for="cardExpiry"><span class="hidden-xs">EXPIRATION</span><span class="visible-xs-inline">EXP</span> DATE</label> <input autocomplete="cc-exp" class="form-control" name="cardExpiry" placeholder="MM / YY" required="" type="tel"> </div> </div> <div class="col-xs-5 col-md-5 pull-right"> <div class="form-group"> <label for="cardCVC">CV CODE</label> <input autocomplete="cc-csc" class="form-control" name="cardCVC" placeholder="CVC" required="" type="tel"> </div> </div> </div> <div class="row"> <div class="col-xs-12"> <div class="form-group"> <label for="couponCode">COUPON CODE</label> <input class="form-control" name="couponCode" type="text"> </div> </div> </div> <div class="row"> <div class="col-xs-12"> <button class="btn btn-success btn-lg btn-block" type="submit">Start Subscription</button> </div> </div> <div class="row" style="display:none;"> <div class="col-xs-12"> <p class="payment-errors"></p> </div> </div> </form> </div> </div> <!-- CREDIT CARD FORM ENDS HERE --> </div> </div> </div> </div>访问读/写功能,可以模拟出来进行测试。

答案 1 :(得分:3)

引用问题:

  

我真的不想将私有方法提取到另一个类,因为从语义上讲它们是这个WorkerThread的一部分。

那是错误。您违反了Single Responsibility Principle

提供“多线程支持”和“做实际工作”是两个不同的事情。您应强制执行“执行实际工作”是私有实现细节。

从这个意义上说:你为自己制定的规则实际上导致你编写难以测试代码。因此,不要“解决”糟糕设计的症状 - 更好地退一步,修复您的设计。

换句话说:

  • 修改您的工作线程,以便能够运行任何类型的工作
  • 单独关注;并将“这种工作”纳入专业课程

通过这样做,不仅可以改善您的设计,还可以使测试更容易:因为现在,您可以单独测试“做实际工作”,无需任何多线程复杂性。你只是断言,按顺序完成后东西才有用。然后你自己测试多线程部分;不用担心实际的工作。最后,一切都很好地融合在一起。

而不是担心如何测试内部实现细节。哪个 - 你没有;另一个答案完全正确!