7 ms·
Still no consensus on testing private methods
- galaxyLogic 5y agoPrivate methods only exist to serve public methods. So if you are testing all the public methods you are at the same time testing the private methods that get called. In the programs I write it is often the case that there are private methods which nobody calls because the program has evolved that way. It would seem wasteful if not misguided to test something which nobody calls but the tests.
- jcelerier 5y ago> Private methods only exist to serve public methods. > So if you are testing all the public methods you are at the same time testing the private methods that get called. that's nice in theory but in practice if your API looks like class my_algorithm { public: float compute_next_value(float); private: void deborgle_fields(...); void reticulate_splines(...); void deboor_network_max_span(...); vector<float> m_tempArray1, m_tempArray2, ...; vector<complex<double>> m_protoscalarField[3]; }; you'll have a much better time if you can test every part of the algorithm individually, even if these steps are entirely specific to this very algorithm and useless to any other code and must not be mingled with with API users under any circumstance (and thus made private)
- Toine 5y agoChange your API then. In this case you usually have 2 classes : a low-level algorithm-specific one, used by a higher-level consumer-centric one. Most of the time, testing private methods is a poor solution to a larger design problem.
- iainmerrick 5y agoWhy expose the low-level algorithm-specific stuff in your public API at all, though? I don't think "just for testing purposes" is a good answer. Unit testing hooks shouldn't be in the public API of a library.
- ahoka 5y agoWell, don't expose them then?
- jesseduffield 5y agoI see this as the main tension in the extracting-class viewpoint. Assuming your language allows it, you can extract out a class that's still private to the current package, meaning that the public API is unchanged. But there are still costs to extracting out that class. If the one public method just calls private method A, B, and C in order, passing the result of one step to the next, and if we don't need to handle different variants of A, B, and C (meaning dependency injection is not necessary), we arguably don't gain much from splitting the original class in two. We're left with a very small class of a single method that's tightly coupled to the extracted class. We can remove the coupling with dependency injection, but now we need to add some code that actually injects that dependency at runtime. So understanding how the pieces fit together is harder. The only benefit to splitting the class that I can think of is in preparing for a future situation where orchestrating the three helper methods becomes more complex, or where you actually do need to handle different variants of A, B, and C via dependency injection. But it feels like premature abstraction to me, single responsibility principle notwithstanding.
- iainmerrick 5y agoI see this as the main tension in the extracting-class viewpoint. Assuming your language allows it, you can extract out a class that's still private to the current package, meaning that the public API is unchanged. But there are costs to extracting out that class. I don't see why the class needs to be extracted in that case. If it makes the code easier to follow, do it; if it adds bloat and boilerplate, don't do it. The key thing is the ability to expose stuff for testing only, not in the public API. Depending on the language, you might not need to extract a class at all -- just make some fields or methods package-private. I guess if your language doesn't provide a way of doing that, extracting a class is a reasonable workaround because you can segregate your public API into high-level and low-level parts, and recommend that end users avoid the low-level parts. But that's not ideal; better to hide the low-level stuff if you can.
- jcelerier 5y agoAny API changes to this would have bigger drawbacks than just making the tests friends of this class.
- Leherenn 5y agoI call those "implementation tests", and I delete the tests once I have finished the implementation. From experience, what you care about in that case is to make sure you implemented the private functions correctly, because it might be some tricky algorithm or whatever. Tests with a lower granularity than the public API make a lot of sense to achieve that goal, it's pretty similar to TDD (though you do not necessarily have the write the tests before the code). On the other hand, in the vast majority of cases, the code, once written, will not be changed. If the public API is changed, then it's likely the internal implementation will be replaced, or changed. In any case, the "implementation tests" will break because the contract has changed. So I delete them, the maintenance cost is higher than the long term value they bring, and non-regression should be ensured by the public API tests anyway. Sometimes, this is wrong, and you will actually need to extend the code in such a way that keeping the "implementation tests" would have helped. I haven't found a good way there to store the test "just in case". You could for instance have a commit that adds them then a commit that removes them, but this is a lot of noise in the history, and the probability that anyone but you can find the deleted tests if they need them is pretty much 0.
- jcelerier 5y agoI find it beyond crazy that you'd go through all this complicated decision state machine when you could just keep the tests and mark them as friends of the class. Why would you ever remove a test ? You don't know when your platform will change things from under your feet, for instance going from x86 to arm, which may break them in subtle ways without you changing anything to your code. And then you're losing hours searching in your 10k commit history the code that had been removed.
- Leherenn 5y ago> Why would you ever remove a test ? Because the cost of building/running/maintaining and generally just having the test around is higher than the value I get from the test. And because I still have unit tests on the public function that should catch issues. Really, I just wrote them to help me during the dev part. Every extra line of code is debt. > And then you're losing hours searching in your 10k commit history the code that had been removed. You're right, I said it was a possibility, but I don't do that, it's not worth it. It has happened twice so far I think that I wished I hadn't removed the tests. I bit the bullet and rewrote them, which is okay because of how rare it is.
- galaxyLogic 5y agoI see your point and it's interesting to think why that is so. When I test the implementation I am basically writing tests for myself to help convince myself that the code is doing what I think it does. Whereas testing the public interface helps other people in the same manner. Note it is possible that a test of a private method might fail yet all public methods calling it would still work correctly according to their "spec".
- wakeupcall 5y agoIn instances where I needed to test private methods, the aim was to provide extra feedback to the failure of a higher-level public method/s that by themselves do not provide enough feedback to pinpoint the issue. It answers the question "what failed?" on a deeper level. Something you'll need to know when the public-method test fails anyway. It's rarely needed on proper API designs (in general such scenarios can be split into a separately-testable object which is not by itself exposed), but it's not too uncommon in my experience. In such cases, all the solutions to test private methods pretty much suck.
- invalidname 5y agoThis is the right answer. There is consensus and it's don't test private methods. Testing private method destroys your coverage data. It effectively makes it a meaningless metric. Coverage isn't just there to show that you tested "everything"... It's there to show that things are actually used in the code and that code isn't dead. Testing private method proves a private method works. But that's not something anyone should care about. It goes against encapsulation and just makes flaky tests that are a nightmare to maintain/refactor.
- galaxyLogic 5y agoAgreed. Creating tests for the implementation means it gets more expensive to replace the implementation with something else, with something better.
- jesseduffield 5y agoI address this point in the post but I'll summarise here: Your argument is equally applicable to higher levels of encapsulation. If you have a class which is private to a package, then code coverage tells you nothing about whether that class is actually used in your package's public API. If you have a package which is private to some parent package, you're in the same situation. You can follow this all the way up to the binary output of an application and say that unless you're doing end-to-end tests which capture user keystrokes and mouse clicks, you're breaking encapsulation (you can make the same argument for a large library). We choose not to run only end-to-end tests because it's expensive both in terms of writing the tests and running them. We choose not to run only unit tests at the lowest possible form of encapsulation because they're more likely to need rewriting when we refactor. Instead we pick out abstractions at various levels of encapsulation that warrant testing in isolation. The decision on whether to test a private method or a private class or a private package differs only in degree, not in kind. To convince those who disagree with you, you'll need to make a case for why private methods should in fact be held to a different standard than other levels of encapsulation. I'm open to being persuaded on this point but I can't think of an argument that convinces me.
- invalidname 5y ago
- jandrewrogers 5y agoIt often does not work this way in practice. The private methods may have sufficiently complex and contextual behavior that it is difficult to adequately test the private methods indirectly via the public interface. This isn't that uncommon for properly architected non-trivial classes. In fact, inducing the private methods to be adequately tested via this indirection can require far more test code than testing directly because of the logic required to create suitably parameterized calls to the private method. It also tacitly exposes internal implementation in the test of the public interface, since this is the only way you can push parameters to the private method interface. In cases like this, you should always test the private method directly because it actually improves the abstraction of your tests away from the implementation details.
- ludamad 5y agoI think this is a strong counterpoint to the "don't test your abstract, implementation-detail machines" philosophy. If you have decomposed a system into iterative passes with pre-conditions and post-conditions it can be hard to ensure any given edge case deep in the process - hence more likely you want to exhaustively test a "private" piece
- Toine 5y agoPrivate methods generally are a code smell anyway. If you have dozens of private methods in your class, something is probably wrong in your general design.
- Kifot 5y agoIn that case how to refactor a class that has 20 private methods? Moving them to another class and making them public would just shift the problem, not solve it
- Toine 5y agoIt's impossible to give a generic answer to this, it always depends on the specific domain. But I found that in these cases, there's always a design problem somewhere. Some responsibilities aren't clear, very often not much thought has been put into the design, and most of the time you can't give an immediate answer, which is why a bad design is chosen and causes a lot of damage down the line.
- barrkel 5y agoPrivate symbols reduce your public API surface, which usually means that it's easier to understand and use and has fewer code paths to test. If your code is a collaboration of objects communicating via public methods, it's almost certainly going to be overly configurable (if it's using dependency injection) and thus be very hard to test every code path, especially given that consumers will probably be able to replace individual objects in the collaboration. It'll also be harder to understand, as objects which are broken out for modularity reasons show up publicly. Minimizing public API surface is particularly important for versioning. If you don't control your consumers - if your API isn't fully internal to an organization and living in some kind of monorepo - then a big public API inhibits refactoring and feature extension as consumers take inappropriate dependencies on your implementation details.
- veltas 5y agoA reason not mentioned is that testing public methods only is more black box testing. It's important to do this not just to allow significant changes to the implementation without affecting the test, but also because if you tie testing too much to your implementation you may miss holes in your interpretation of the requirements/interface that are better caught in a black box test. If you want coverage then private method testing is giving you fake or inferior coverage. Those hard to reach paths are only truly tested via the public interface (i.e. called by the function that will call them in practice, not your contrived test function).
- bedobi 5y agoThis is so important but even most professional software developers and testers don't seem to understand it. Tests are not supposed to break on every little change to the code, or even sweeping changes in implementation. If they do, they're not very good test. https://testing.googleblog.com/2013/08/testing-on-toilet-test-behavior-not.html https://testing.googleblog.com/2013/08/testing-on-toilet-tes... https://medium.com/expedia-group-tech/test-your-tests-f4e361818720 https://medium.com/expedia-group-tech/test-your-tests-f4e361...
- Sankozi 5y agoI disagree. You are basically saying that only end to end tests are very good tests. There are different reasons to have tests. Unit tests often break even during small refactorings but are great to quickly cover of lot of edge cases of some complex piece of code. They also quickly point to what exactly is wrong. End to end tests on the other hand should be almost immune to refactoring problems, but they are very slow and often it is tricky to find where the bug is or even if there is a bug at all in the application - in those tests bugs are very often in test code.
- carlmr 5y agoAs always, all the extremes are wrong.
- marcosdumay 5y ago
- politelemon 5y ago> With so many contradictory viewpoints, somebody has to be wrong! But who? I think it's the opposite, there absolutely doesn't have to be a wrong. Assuming someone must be 'wrong' is not a healthy viewpoint to take. What we're running into is a limitation in the languages and frameworks we use, and we are assuming that those languages frameworks are right, they are the only way things should be done. That limitation is then being expressed as the various viewpoints that author has listed. I'm glad the author took the time to enumerate the various viewpoints and I'm sure there are more!
- asimpletune 5y ago> What we're running into is a limitation in the languages and frameworks we use Can you elaborate on this point more?
- chriswarbo 5y agoAn example which comes to mind is how Racket handles tests: they're generally written in "sub-modules" of whatever they're testing, and hence they have access to "private" (AKA un-exported) definitions. https://blog.racket-lang.org/2012/06/submodules.html https://blog.racket-lang.org/2012/06/submodules.html Framing discussions around "classes and methods" is a rather narrow-minded view, which ignores lots of potential solutions.
- jesseduffield 5y agoI agree with your point about the dangers of right/wrong thinking, though when I wrote that line I was specifically thinking about people who say we should never test private methods vs people we say we should always test private methods, in which case they truly can't both be right. I've updated the post to make that clearer. On your point about language limitations, I also wonder about this. I vaguely recall coming across a post that mentioned testing private methods just wasn't an option in various languages in the early days, and it's possible that were that not the case, we wouldn't have so many advocates of the never-test-directly viewpoint. That's not to say that the viewpoint is wrong though.
- Loic 5y agoIn my chemical engineering work, I have often private routines I want to test. Pardon me, but this is Fortran code, so I cannot have "complex" class structures to allow different level of testing without complicating the code too much and making it unreadable. The solution is "stupidly simple". I have at my module level a public subroutine with the name "test_module" which performs the tests of all the private subroutines of the module I want to test (these are usually analytical derivative calculations and stuff like that). Yes, I have test code in my module, but in practice, after 10+ years of using this pattern, nobody had issues with it.
- feanaro 5y agoThis is also the recommended way of structuring things in Rust. It works pretty nicely.
- dirkf 5y agoIn the C world I sometimes do something similar: the C file with the test code simply #include's the actual source file and gets compiled into one executable (together with some mocks). Not too dirty (ahem...) and allows you to test various internal parts. And I must admit I got the idea after looking into Rust :)
- JonChesterfield 5y agoIn C I just write the tests in the same source files as the things they're testing. Some interface tests get their own source file. All the tests end up in the "release" binary, along with the application code. Separate test_main entry point to run the tests instead of the application. If I don't want the tests available, marking test_main static and deadstripping rips them all out.
- thot_experiment 5y agoI'll have to keep this in mind for the future, it seems like the KISS solution to the problem.
- IshKebab 5y agoI said this on Reddit but I think it's pretty clear that the "test private methods sometimes" view is correct. Some public APIs make it infeasible to test the code using just the public API, but if you can do that then it's clearly preferable because you won't have to rewrite tests when the implementation changes. This is a nice overview of the viewpoints anyway.
- recursive 5y agoIt's equally clear to some of us that the "don't test private methods" view is correct. But clarity is not consensus.
- IshKebab 5y agoI think the people that think that just haven't come across a situation where that doesn't work yet. I'd guess there are entire fields where it does work, e.g. crypto or compression.
- thot_experiment 5y agoI appreciate that the author calls out "not having private methods" as a possible solution. That's certainly my approach, I feel in general private methods are akin to docker. Yeah they're a useful tool sometimes, but only because of the road strewn with blunders that got us here in the first place.
- freetime2 5y agoCan you elaborate more on some the challenges you have faced with private methods?
- thot_experiment 5y agoHonestly I've never used them of my own volition. So it's not so much that I've faced problems with them, it's just that I've never felt like they solved any problem I had. I don't even really use "methods" strictly speaking, in general I'll use a dictionary of functions if I want to group functions together semantically, and I'll emit such a dictionary from a closure if for example I need to precompute a lookup table to be used for multiple related calls. I've had more negative experiences with being denied the ability to do something by overwrought architecture than shooting myself with a footgun someone left in, but importantly I think my approach generally leads to more composability and agility.
- freetime2 5y ago> I'll emit such a dictionary from a closure if for example I need to precompute a lookup table to be used for multiple related calls Isn't this analogous to using private methods, though? I.e. you have some logic to precompute the lookup table that isn't accessible to users of your dictionary of functions? Am I misunderstanding how this works? Or are there benefits of this approach vs. for example having a private method "precomputeLookupTable()" that gets called in a class constructor?
- LAC-Tech 5y agoDidn't unit testing come out of the Smalltalk culture? Smalltalk has no private methods, or public properties. So if there's stuff that's an implementation detail it goes in another object.
- hughrr 5y agoI think this is overthinking it. The only thing that matters are the collaborating interfaces. If you are writing a test case it should possible to act upon it through interfaces only. If you can’t do that then you probably screwed up the design and should refactor it. This is where SOLID comes in and black box testing.
- andybak 5y agoOverthinking what? The article enumerates and compares different viewpoints - one of which is the one you've expressed above.
- asimpletune 5y agoThe right answer to almost any question that's worth asking is "it depends". In the case of testing private methods it's no different. For example, testing private methods can lead to code having to be refactored every time you change something. This is bad, especially when presumably those methods are utilized by going through the public interface, which conveniently shouldn't change a lot. However, it also depends on how the code is structured. Maybe it's a large systems project where there are huge private libraries that let you do important stuff. Obviously that needs to be tested. Or maybe you have an abstraction for dependencies that need to be injected at runtime to do real work, but you have a private implementation that's not exposed publicly. Even in that case, for example, it really depends. So, it depends, and it probably depends on what do you get for doing things a certain way vs another. I'm going to say most of the time "no", but it's definitely not a rule.
- freetime2 5y agoExactly - we shouldn’t be overly concerned with whether the method is public or private. Instead we should be concerned with things like: Are these tests going fail any time someone makes the slightest change to the implementation? Do these tests require a ridiculous amount of setup? Are these tests going to run so slowly that they adversely impact the velocity of the entire team? I agree that as a general rule it’s preferable not to test private methods directly. But if testing a private method is demonstrably more efficient than getting at it through public methods, and the tests don’t end up being too brittle, then that’s probably what you should do. You could also take a look at refactoring the code to make it easier to test - but again only if that actually improves things.
- withinboredom 5y agoI look at it like this: what are the inputs/outputs of what I’m testing? Is it calling another library to do work, spy on that. Is making side-effects in the system, watch that. The only time I’d use internal/private methods directly in a test is when setting up to use the public methods would be tremendous (imagine configuring a database driver to fail in a certain way, for example). Most of the time, I see private methods being tested when the library is “in the middle” of other libraries, or is not properly abstracted.
- andybak 5y agoToo many of the comments here are just restating points made in the article without advancing on them. I know "did you read the article?" is verboten on HN but people should at least attempt to respond to points made within and move the discussion forward. This article in particular is weighing up and contrasting various viewpoints so very little value is added in repeating one of those viewpoints unless you also explain why you think the interpretation originally given was lacking or flawed.
- deleted 5y ago[deleted]
- iainmerrick 5y agoI think the best tool for this is package-private visibility. It's often much easier to write a test if you can poke at the internals a little bit, but it's a bad idea to widen your public API just so you can do that. So, make your internals package-private and put the test code in the same package. Unfortunately this isn't easy to do in all languages (e.g. Java gets it right, but Kotlin bases visibility on build packages rather than namespaces).
- Cthulhu_ 5y agoAs always there's no one answer because "it depends". One anecdote, I'm currently building a bit, complicated (in terms of domain logic, it's just a CRUD app; rest api, database, xml file writing) Go app, which has a very simple visibility system; any identifier that starts with a Capital letter is public, anything with a lower case is (package) private. There's some more details if you call a folder `internal`, but that's for libraries. Anyway, one of my packages, `xml`, has two or three public functions; input is a domain model, output is a (byte array containing) an XML document. Simple and straightforward. But internally, what is included in the XML depends on a ton of business related rules; if this field is this value, that tag should not be written; if that field is set to that value, this tag should be written but emptied out; if this field is this domain struct value, it should be written as this string. That kinda logic, times twenty. I can test it using the public API just fine, it just makes the unit tests very... voluminous; for every module, times every edge case, I'd need to create a full domain object and a full expected XML module. That's over 50 LOC per test. This package currently has >200 test cases. I decided to test private methods. Each private method has a table test containing each module's particulars and edge cases. It makes more sense in my head, it's faster to execute, etc. Especially now that I work in Go, I'm more and more Aware that code is not so much about code volume or cleverness, but it's about managing complexity. I'm building an application that will juggle >100 domain entities with dozens of fields each, and I have to write it in such a way that I - and hopeful future maintainers - can manage this complexity. If that involves testing private methods, so be it. It doesn't feel bad, and I'm very confident that once this logic is written, it'll remain mostly untouched for the next decade.
- dmitriid 5y agoThey could be tested if languages supported doctests like Elixir: https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#doctests https://elixir-lang.org/getting-started/mix-otp/docs-tests-a... however, increasingly my view is: the less you test methods and components in isolation, the better. Unit tests are highly overrated and used too much to the detriment of all other testing.
- deleted 5y ago[deleted]
- drakonka 5y agoThis is one of those debates I'd have totally gotten into a few years ago and now just cannot be bothered. I have my own set of testing approaches and preferences that _usually_ work, but sometimes something else makes more sense and then I do that. Sometimes I find it is just more efficient to test `privateFunctionA()` and fail out early. This does not prevent me having a test for `publicFunction()` that runs through `privateFunctionA()`, `B()`, `C()`, and `D()` to test the full flow of interaction between them. I refuse to make a function public _just_ to test it and would like my public interfaces to be as small as possible. This means a lot of private behavior to test underneath, and sometimes it just makes sense for me to test those chunks individually. Many people wouldn't agree, and that's cool - it just means another approach works better for them. If I have a choice and am writing something from scratch, I'll do it my way. If I'm working in an existing codebase I'll err toward sticking to the existing standard (or suggest changing it if I don't think it's working very well).
- pagade 5y agoOne alternative/compromise not mentioned is to make the method 'protected'. This is usually a reasonable compromise in languages like Java. The test can access such method since it follow the same package hierarchy as the src.
- jve 5y agoTLDR: Language should provide additional constructs to interact with private code. Am I the only one that feels like this all just points out to flaws of the language itself? We should not have to consider changing private to public just because we want to test that function. Moreover I'v seen comments on docs.microsoft.com along the lines "not to be used", "for internal use only" etc that may be a result of language shortcomings. C# has this attribute InternalsVisibleToAttribute[1] where you open up all your internal stuff to other (test) assembly that solves one of the problems: your test assembly accessing YOUR code assembly. Now for the wishlist. The issue with InternalsVisibleToAttribute is that the assembly author controls this. I'd like to control this as a consumer too. Given that (citation) "The idea is that when writing library code you couldn’t possibly know what method your clients will want to use ahead of time, and defaulting to private methods will cause more problems for you and your clients than defaulting to public (or protected)." - so why not take responsibility to myself of using code that may break in next update? Like PrivateVisibleFromAttribute. Or a language construct like unsafe {}, but private {}/internals {} where intellisense will happily list all private/internal methods. Maybe not a good idea for all cases, but I can see this useful: "that library X won't need many updates and it has that complex function I'd like to use to exactly mimic functionality X". Or: this legacy system written 20 years ago won't have any updates, but I must implement XYZ, part of which already private functions by original developers provide. Or I may want to extend that private class, override with my functionality (re-using parts of that code) and provide bindings for runtime to use MyVendorClass instead of VendorClass. The thing is, you can do this with C# Reflection (access private members), but it's cumbersome. Better have language provide necessary tools and most of this discussion wouldn't happen as test assembly will happily tie into internals. [1] https://docs.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.internalsvisibletoattribute?view=net-6.0 https://docs.microsoft.com/en-us/dotnet/api/system.runtime.c...
- recursive 5y agoYou might like Uncapsulator. https://github.com/albahari/uncapsulator https://github.com/albahari/uncapsulator
- Jenk 5y agoMy take: private methods are not _designed_ they are _extracted_. Therefore, for the purposes of demonstrating/articulating what I mean - with "Proper TDD™" I am always at a state during the Red and Green stages, that there is no private method to test. They just don't exist, because I have thus far only done the simplest possible thing to pass the test. (This is the same course of events when I am not using tdd.) After the Refactor there might be some private methods, but they will already be covered. As for the API argument, if you don't want implementation exposed, then don't expose the class. This is what Interfaces are for. Need to expose a class? Then make a "contract" class such that the stuff you don't want exposed isn't.
- efficientsticks 5y agoIn an ideal world, a class would be all public fulfilling some abstract interface which is pertinent to the logical substance of the solution, and those methods would perform their operation using other components which are private final and supplied as constructor arguments. This is called “over-engineering” by some, but really it is the most testable and refactorable approach to creating programs (other than being a team of PhD Haskell programmers). The problem is simply that programming hours are expensive and we don’t got time for this methodology, in general, just as we don’t have time for Ada or formal methods, in general. AI co-programming will change all of this. Edit: this approach is different from Option 1 in the article because it’s about refactoring and not just flipping method visibilities even where it makes no sense for the interface.
- rvr_ 5y agoI don't test private methods and I like to use them a lot. When refactoring, if a private method is unused, both IDE's and linters will warn you, easing the process of deleting dead code. If you extract private methods into separated classes and expose them as public methods, deleting unused code becomes hard (and harder with multiple repositories).
- Supermancho 5y ago1. no[1] 2. yes 3. no 4. no 5. no[2] [1] CAMs do not change the issue of functional accuracy in any way. This is irrelevant. [2] This is the result of developers thinking about their objects designs differently, which is good. Class access modifiers are for mixin property selection. That's what they have always been about. The idea that CAMs are for object interface definition is a cargo cult that developed around Java early on (because Java was rather primitive), unnecessarily mixing the concerns. Eventually it ended up in the classroom, to the detriment of the industry. Similarly "final" is an ironic language mechanism that disempowers the users it's meant to aid, because it's assumed the indicator "constant" is insufficient.
- ravenstine 5y agoPrivate methods shouldn't be tested, and if you feel like they need to be tested then chances are your private methods should be public. I've seen private methods used within internal projects at companies, and admittedly I've created many private methods in this condition, but unless what you're shipping is a library then what exactly is the point of making your methods private? To stop the developers from misusing their own code? For the most part, I sometimes use private methods in my own projects as just a way to make it more immediately apparent that something is just supporting code for something else. If no one else is using the code as an API, and it somehow turns out that the private code needs to be tested directly, it becomes a candidate to be promoted to public because there'd be no reason for it to be private at that point.
- oxfordmale 5y agoThere are too many "dogmatics" in Software Engineering. You want to unit test code that is worth while testing from a business point of view. If a private method contains a lot of complex business logic, you do want to test it, however, not necessarily if this code can be easily tested by calling one of the public methods.