TDD Study Notes [3] --- do I need to test non-public methods ?, Tdd Study Notes

Source: Internet
Author: User
Tags visual studio 2010

TDD Study Notes [3] --- do I need to test non-public methods ?, Tdd Study Notes
Preface

In Visual Studio 2012, there is an important change to the Unit Test section:

Originally, for the non-public part of the test object, developers can use the accessor automatically generated by Visual Studio 2010 to perform the test. However, in Visual Studio 2012, this function is removed.

The principle behind Accessor is to make all the objects in the object public through dirty reflection. Visual Studio will help you synchronize and generate accessor operations after updating objects and performing design tests. (I have not studied the principle in depth, and I am not sure about it. But this is basically the concept)

This feature was originally considered convenient and practical (including the one I thought when I wrote the test a long time ago). Sorry, it was removed after Visual Studio 2012.

Next, this article will explain whether unit tests should be conducted for non-public parts of the test object.

Significance of Unit Testing

In a word :「Unit testing is used to simulate how to use the test target object externally and verify whether the behavior meets expectations.」.

Therefore, the focus is on how to use the test target object externally.

Let's return to the encapsulation principle of Object-Oriented. The purpose of encapsulation is:

With the recognition of unit testing and encapsulation, we will explain why unit testing only needs to test the public behavior of the target object.

 

Only test Public behavior?

According to the meaning of unit test and the purpose of encapsulation 「External users do not need to understand or understand the behavior of the target object.」. Since unit testing simulates external operations, it only simulates and verifies the public behavior of the test target object.

But some friends may be confused. What should I do if the non-public method is used? Unexpected? How can code coverage be upgraded? How do we know that these non-public behaviors do not work as expected?

It is normal to have these questions, because I also had the same questions at the beginning, but after getting started with TDD, I became more familiar with the nature of Unit Test.

The reason for the existence of the so-called non-public behaviors must be that some public behaviors will use these private or protected methods, if the object has a private or protected method unrelated to the public method, it is a problem in design. These non-public methods have no meaning at all. Because these methods are not used when the target object is used externally, it is meaningless to declare a variable but not to use it.

When private or protected methods are related to public methods, unit tests for public methods will cover these private or protected methods, which are part of the public method, for external users, it is impossible to tell what is private or protected, because only focus on the external visual behavior of the object.

Therefore, in the actual unit test, if a public method of the test object contains a private method, and the private method is dependent on an external object or service, when testing this public method, you must write stub object to simulate the dependency interfaces in the private method. This is why unit test is called a white box test. However, it must be emphasized that external users cannot identify which part is public method and which part is non-public method.

To sum up the above statement, the testing coverage of non-public method is determined based on the input used in the public method call.

Is it possible that when public method is tested, or even the content coverage rate of public method subjects is 100%, the coverage rate of some non-public methods is very low? Of course it is possible, but it is necessary to clarify the code that is not covered.

If a non-public method is not covered by the test, it is a code such as a reminder or assertion, it is normal. This may be because a reminder has been given before non-public method is called, so that the reminder in non-public method will never happen. However, because of the robustness of the system, the assertions, reminders, and verification are not limited. This is because I don't know if there is any reminder before other methods are called in the future.

So, in private or protected method, the code without reminders or assertions is not covered yet? This is an alarm, indicating that the Code may be over design or is useless at all. Because all external behaviors and possibilities of this object have been simulated once, but these uncovered codes are not used, doesn't this mean "these codes are not currently used? The YAGNI principle is to say this :「You ain't gonna need it!

As long as the public behavior is as expected, even if the private or protected method is hard-code, it is not flexible, it is a stupid way of writing, for external use, it does not care, because there is no sense.

This is also the spirit advocated by TDD. If all the usage behaviors are as expected, the function is completed. In addition, the production code written based on the test hardly contains any code that is not covered by the test, because the production code is written to satisfy the test. No unused production code is required. Therefore, over design can be avoided.

 

What about non-public behavior testing?

As described in the above paragraph, we cannot convince everyone, "Why remove existing functions ?」

If you do not need an accessor, you still want to continue using it in VS2012.

Back to the purpose of encapsulation ,「Encapsulation changesIt has always been an important design principle in object oriented design. Have you ever tried "private and protected 「As some requirements are updated, unit test programs need to be re-adjusted, designed, or modified, and the frequency and scope increase the maintenance cost of tests.Experience. If so, this is why developers do not want to write unit tests for non-public methods.

Focus on the unit test of Non-public method, and write it to developer. This is because changes need to be encapsulated to convert the content into private or protected, so as to present a sense to external users when the changes are expected, that is, to reduce coupling, that is, the minimum knowledge principle.

At present, the unit test uses some mechanisms to access these encapsulated behaviors? It was originally known that these things are likely to change constantly, but they are accessed and tested. As a result, the maintenance and update frequency of unit testing increases, which does not violate the purpose of encapsulation?

From the perspective of using objects, the user does not care about these changes at all, but the unit test uses dirty methods to harden these undisclosed behaviors, resulting in increased testing costs, as a result, some unknown developers shouted "testing is very costly, time is increased a lot, and maintenance is difficult 」. I just want to say :「This is not a problem of North-South boxing. It is your problem..」

 

Conclusion

To be honest, I was surprised to know that Visual Studio 2012 had removed the accessor function. I felt that it was necessary to force developers to use TDD for development.

However, after combining the object-oriented principle, the spirit of TDD, and the basic meaning of unit testing, with the above thinking process, I feel that I only want to test the public method, it is not recommended to test the private and protected methods. This is correct and important.

Therefore, sharing such a process of thinking and inference with your reference may not be completely in line with the reason why Visual Studio 2012 removed the accessor. This is just my own understanding and ideas, however, since I first came into contact with unit tests, how to test the private method has been bothering me for a long time. Although my head has a rough outline, I have been unable to clarify it clearly.

 

Supplement

Here is a very good article, which is quite comprehensive, including concepts, practical considerations, and considerations in the process. See: Testing Private Methods with JUnit and SuiteRunner

Supplement: VS2012 removed the accessor function from the function of Automatically Generating Unit Test code because of the original accessor generation mechanism, which is too coupled with MS Test. (After Visual Studio 2012, it is expected to be elastically combined with other Unit Test providers .)

 

Reader's questions

For some readers, I will add some questions at the end of the article. If you want to know or ask questions, please leave a message.

 

Q1. The article only mentions public, protected, and private. What about internal?

A: This is a great question, because I did not mention the internal part in this article.

First, the definition/intention of internal is that it can be viewed within the same component, that is, the object I want to make public in this component, however, no one else can see or use the components. (This design can effectively control the dependency scope)

As mentioned above, unit testing is intended to simulate the interaction between objects. It indicates whether an internal object is tested or not. Of course, because other objects use it, we need to think about "how to use it 」.

However, from the perspective of a test project, it refers to the library of the production code. Therefore, from the perspective of the test project, it cannot be seen that the production code is declared as an internal object, but what should I do if I want to test the internal object in the production code?

In. NET, it is quite simple. You only need to set it through the attribute InternalsVisibleToAttribute. You can solve this problem by specifying the production code library to the test project.

 

Q2. if no private test is performed, How do I know which code is wrong when a problem occurs? Or if it is not covered, it means it is not protected by testing.

A: This question is to digest this article slowly. After the article is actually written, it will gradually open the cloud and see Qingtian.

When we only use the test thinking, it is strange not to "test the private method" because it is alive, but it can be immediately known if it is not tested.

This is also one of the thresholds for TDD. Let's look at the purposes of the previous articles. What is the purpose of the system?

To meet users' needs and external needs correctly. Since the object orientation is used for design, since these things are encapsulated, external users cannot see and use them, nor should they see and use them. The significance of our encapsulation lies in encapsulation changes. In this case, other methods are used to test the private method in the object, which only increases the burden on the future, because it will definitely change.

The original private change can hardly affect any part except the object itself. So it can be changed.

As you can see from the outside, you cannot easily change the method. Once you want to change the method, it may affect many test programs. On the contrary, the production code will not have much influence. However, if the test program needs to be maintained or rewritten, this is not necessary at all.

Finally, if you use TDD for development, you will not encounter this problem at all.

Because, you only want to implement public behaviors, and always write public content as the starting point. Probably only when refactoring occurs, private and protected will appear. At this time, the private method is the content you originally put in the public method.

If the code coverage of the original public method is 100%, it will not change to 50% because you move to private. If the reconstruction does not cover the scope, it is the bad smell of over design, which is a sign.

Here, we need to combine TDD and Refactoring to form a whole and enjoy its beauty without any worries. Again, the content of the private/protected method, In TDD, is basically because the extract method of refactoring produces some function content originally placed in public/internal. Instead of writing private functions directly, unless you are the top-down operator that first defines the framework of the program. But in the end, the private function is still part of the public function content.

Therefore, you must be particularly satisfied with whether you have performed all representative situations for testing for externally visible behaviors. If it covers all objects, including exception handling, the uncovered parts of this object can be basically deleted. It will never affect external use.

 

Note: This series is a process for me to record the blog digest of danale after I graduated from the development industry one year later, non-original, thanks to 91 and other predecessors

 

 




Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.