Unittest und private Klassenvariable?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hi,

für einen unittest muss ich auf eine als privat markierte Variable zugreifen, dass leider fehlschlägt.
Hier ist der Testcode:

Code: Alles auswählen

import unittest
class Test:
	__a = 1

#UnitTests
class Unittest_Test(unittest.TestCase):
	def test_a(self):
		self.assertTrue(Test.__a == 1)

if __name__ == "__main__":
	unittest.main()
Der Fehler ist:
AttributeError typeObject "Test" has no attribute "_Unittest_Test__a"

Ich kann jetzt natürlich einfach _a statt __a schreiben aber ich würde gerne Wissen wie ich das in Zukunft richtig mache.
Euch noch eine gute Nacht,

p90
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Doppelte Unterstriche am Beginn eines Namens dienen nicht dazu, den Namen als privat (im Sinne von Java, C++, ...) zu markieren, sondern um Name Mangling auszulösen. Mehr dazu hier: http://docs.python.org/3.3/tutorial/cla ... -variables.

Es gibt allerdings diese Konvention: wenn ein Name mit einem einzigen Unterstrich beginnt, dann gehört dieser Name nicht zum öffentlichen Interface und sollte von außen nicht verwendet werden. Die Verwendung ist aber möglich und nicht verboten. Man sollte halt wissen, was man tut. Wie Guido van Rossum immer sagt: We're all consenting adults.

Im Übrigen bin ich der Ansicht, dass Unittests das öffentliche Interface testen sollen. "Private" Namen, deren Werte nicht irgendwie zum Verhalten "öffentlicher" Methoden beitragen, sind ein Unding. Undinge brauchen keine Tests. Folglich genügt es, das "öffentliche" Interface zu testen, da dabei - qua Voraussetzung - alles "private" implizit mitgetestet wird.
In specifications, Murphy's Law supersedes Ohm's.
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Ah!
Danke für die Erklärung.

Noch etwas zum Hintergrund.
Mir war das ganze bei einer konverter Klasse aufgefallen die zwischen meinem python Code und
einer Datenbank steht. Innerhalb der Klasse ist das Mapping zwischen den Werten in der Datenbank und den Werten in Python
definiert und alle Interaktion findet nur über diese Klasse statt. Der Python Code sollte also gar nichts über dieses Mapping wissen und ergo ist das Mapping auch nicht teil des Interfaces.
Das Mapping muss aber billinear sein. Um dies zu testen hatte ich einen Unittest geschrieben und hatte dann genau dieses Problem.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@p90: Aus der Fehlermeldung wird ja schon ersichtlich, wie Python mit __ umgeht: Finden Python innerhalb einer Klasse ein Attribut (es muß nicht unbedingt zur aktuellen Klasse gehören) das mit __ anfängt wird es umbenannt in _Klassenname__Attributname. Die Umbenennung kannst Du natürlich auch irgendwo anders von Hand machen. Ansonsten gilt was pillmuncher geschrieben hat: Das ist für's debugging manchmal ganz nützlich, in Unit-Tests hat es aber keinen Sinn, Implementierungsdetails zu prüfen.
Antworten