3

we have a module of static methods in our python app. these methods use a lot of private (e.g: "__do_sub_task2(**args)") I would like to write unit tests for these private static methods within this module, but I am getting refernce errors.

is there a way to do this?

update: adding scenario

I have a module file named 'my_module.py' contents of said file is as follows:

def public_method_foo(my_number):
  return __sub_method_bar(my_number * 10)

def __sub_method_bar(other_number)
  return other_number + 11

update #2 The reason I am asking this question is because I have a similar scenario as above, but when I add the following reference to my test.py module file:

from my_module import __sub_method_bar

and try to use it in my test, I get the following exception in my test

global name '_MyTests__sub_method_bar' is not defined

Nathan Tregillus
  • 6,006
  • 3
  • 52
  • 91
  • Aside - typically you do not write unit tests for private methods, but instead the public methods that use them. – C.B. Apr 30 '15 at 00:36
  • but that would not be a unit test, it would be an integration test of both methods – Nathan Tregillus Apr 30 '15 at 00:38
  • Are these really `@staticmethod`s? Or do you mean something different by "static"? (And if so, what?) – abarnert Apr 30 '15 at 00:39
  • Not necessarily. E.g. http://programmers.stackexchange.com/questions/100959/how-do-you-unit-test-private-methods – C.B. Apr 30 '15 at 00:40

1 Answers1

5

What you have are not methods, not private, and not static; they're just plain old public functions in the module. So you call them the same way as any other function. For your example:

>>> my_module.__sub_method_bar(5)

That's it; nothing tricky.*

* Well, there is one tricky thing, but it's probably not going to affect you here: If my_module doesn't have an __all__, and you do from my_module import *, you will not get any of the globals (including functions) whose names start with _. But normally your unit tests are going to import my_module, so this won't be relevant.


Methods are callables that are members of a class. And methods can be private ("private" in this sense means "visible only to this class, not even to super- or sub-classes", so it doesn't make sense for anything but methods). The tutorial chapter on Classes explains how private methods are implemented, with name-mangling. Methods (private or otherwise) can also be static ("static" in this context means "does not take the normal self", so again, it doesn't make sense for anything but methods). Either way, for a private method, you have to manually demangle the name to call it from outside:

>>> thingy = Thingy()
>>> thingy._Thingy__private_method(5)
>>> Thingy._Thingy__private_static_method(5)
abarnert
  • 354,177
  • 51
  • 601
  • 671
  • my question is not about a class, it is about a private static method in a module – Nathan Tregillus Apr 30 '15 at 00:40
  • @NathanTregillus: That doesn't make any sense. A method is part of a class; that's what makes it a method. If it's just a function, modules don't have private functions the way classes have private methods; you just call it as `__do_sub_task2`. And I still don't know what you mean by "static". – abarnert Apr 30 '15 at 00:42
  • please see example above – Nathan Tregillus Apr 30 '15 at 00:43
  • I think you'll need to provide an example, because static methods are part of classes. In fact, that is exactly what it means; a method moved into a class for the purpose of logical arrangement. – theherk Apr 30 '15 at 00:43
  • If this code `__do_sub_task2(**args)` (your example) is not in a class then it is neither a method nor private. – theherk Apr 30 '15 at 00:45
  • 1
    @NathanTregillus: OK, I've updated the answer to answer what you're actually trying to ask, and also to explain why it's not what you actually asked. – abarnert Apr 30 '15 at 00:48
  • thanks, sorry for the newbish questions. only been working in Python for a month – Nathan Tregillus Apr 30 '15 at 00:51
  • ok now i am lost. this answer says there is no such thing as a private method, but then mentions __all__ will denote what is public. I have attempted the example provided with "from my_module import *" but no dice. I get the following error " global name 'my_module' is not defined" – Nathan Tregillus Apr 30 '15 at 01:01
  • @NathanTregillus: You're reading your own incorrect wording into things. First, the answer does not say "there is no such thing as a private method", it says there _is_ such a thing as a private method, but only methods can be private methods. The answer also does not say that `__all__` "will denote what is public"; there's a sense in which that's a reasonable thing to say, but not if you're using "public" to mean "the opposite of a private method", because that's not at all what it does. – abarnert Apr 30 '15 at 01:04
  • @NathanTregillus: meanwhile, you did you change your attempt to `from my_module import *` when the answer explicitly says you probably shouldn't do that, and explains how it can add a new problem? – abarnert Apr 30 '15 at 01:05
  • sorry, I missread the fine print that you SHOULDNT use "from blah import * " finally found a workaround. I did the following to my import: – Nathan Tregillus Apr 30 '15 at 01:07
  • 1
    from my_module import __sub_method_bar as sub_method_bar – Nathan Tregillus Apr 30 '15 at 01:07
  • when I used this aliased method, I was able to call the private method – Nathan Tregillus Apr 30 '15 at 01:07
  • just as a tip, _methodname is not really private. "private" in python is more a convention for devs :) [Here](http://stackoverflow.com/questions/70528/why-are-pythons-private-methods-not-actually-private) is more about this. – Reishin Apr 30 '15 at 06:42
  • 1
    @Reishin: He's asking about `__methodname`, which is different from `_methodname` (but only in methods, not in module-level functions). – abarnert Apr 30 '15 at 06:58
  • 1
    @abarnert possibly you mean "in classes" :) – Reishin Apr 30 '15 at 07:51
  • 1
    @Reishin: Yeah, either "in classes" or "for methods", not "in methods". Apparently much of talking at Germans today has broken my prepositions. :) – abarnert Apr 30 '15 at 08:07
  • Thanks guys and/or gals, my previous experience with other languages, the terms methods and functions were interchangeable, so knowing there is a difference in python terminology is a good-to-know! – Nathan Tregillus Apr 30 '15 at 15:55
  • @NathanTregillus: Out of curiosity, which languages? I know that Dylan made a big deal out of "functions are just methods with no overloads", but I can't think of anything more mainstream. – abarnert Apr 30 '15 at 23:22
  • was a C# developer for a long time. since everything in C# is in a class, you only had static methods, and member methods. – Nathan Tregillus Apr 30 '15 at 23:24
  • @NathanTregillus: Ah, C# just doesn't _have_ functions, like Java, so it forces you to write static methods as a substitute. You can actually do the exact same thing in Python—create a useless class, and define a bunch of methods with the `@staticmethod` decorator, and then use them instead of functions—but you don't have to, and very rarely want to. – abarnert Apr 30 '15 at 23:31
  • @NathanTregillus: Except… aren't lambda expressions functions, not methods, in C#? Or are they just anonymous methods of anonymous classes? – abarnert Apr 30 '15 at 23:33
  • you are right, but there are some strange closer like logic, like you can access outer scope variables within the lambda I believe. it gets complicated, and I avoided that stuff when possible – Nathan Tregillus Apr 30 '15 at 23:39
  • 1
    @NathanTregillus: Well, in Python, you can access outer scope variables from any function, so you can't really avoid it. But on the plus side, unlike C# and many other languages, Python's `lambda` works exactly the same as its `def` except for being anonymous and an expression, so you don't have to learn two completely different things. :) – abarnert Apr 30 '15 at 23:52
  • awesome. Thanks @abarnert. I really appreciate people like you helping us newbies learn new stuff. It makes learning new languages fun. – Nathan Tregillus May 01 '15 at 00:07