Pythonic way do testowania np "subprocess"?

0

Mam klasę która korzysta z subprocess.call,i zastanawiam się jak ją właściwie przetestować.

Pisząc w Javie, na pewno użyłbym Dependency Injection i po prostu wsadził w teście mocka. Python to jednak nie java. W większości pytań nt testowania takich metod większość jednak jest za tym żeby w testach po prostu podmienić globalny subprocess.call na mocka.

Nie jestem pewien które z nich jest okej, ktoś coś doradzi?

0

Może mockowanie zaimportowanych modułów byłoby najlepsze?

1

Możesz użyć https://docs.python.org/3/lib[...]mock.html#unittest.mock.patch
Albo niech funkcja będzie wstrzykiwana do klasy przez konstruktor. Domyślnie niech to będzie subprocess.call, a w testach możesz sobie podmienić na co chcesz.

1
import subprocess
import unittest.mock

class Foo():
    def foo(self):
        subprocess.call("pwd")
        return "ok"

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('subprocess.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()
0
Spearhead napisał(a):
import subprocess
import unittest.mock

class Foo():
    def foo(self):
        subprocess.call("pwd")
        return "ok"

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('subprocess.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()

A czemu nie działa jak zaimportuję call?

from subprocess import call
import unittest.mock

class Foo():
    def foo(self):
       call("pwd")
        return "ok"
0

Inne przestrzenie nazw.

from subprocess import call
import unittest.mock

class Foo():
    def foo(self):
        call("pwd")
        return "ok"

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('__main__.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()

Patrz: https://stackoverflow.com/que[...]om-import-statement-in-python

0
Spearhead napisał(a):

Inne przestrzenie nazw.

from subprocess import call
import unittest.mock

class Foo():
    def foo(self):
        call("pwd")
        return "ok"

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('__main__.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()

Patrz: https://stackoverflow.com/que[...]om-import-statement-in-python

Czyli, gdybym zrobił

import subprocess
import unittest.mock

from my_second_file import Foo

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
            with unittest.mock.patch('__main__.call'):   # to nie zadziała, bo "call()" jest wołany w "my_second_file", tak?
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()
0
Spearhead napisał(a):

Inne przestrzenie nazw.

No to nie, to ja chyba podziękuję za takie rozwiązanie bo testy wiedzą wtedy o szczegółach implementacyjnych klasy (np wiedzą czy używam subprocess.call() zamiast call()).

0
import subprocess
import unittest.mock

from my_second_file import Foo

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('my_second_file.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()
0
Spearhead napisał(a):
import subprocess
import unittest.mock

from my_second_file import Foo

class TestStringMethods(unittest.TestCase):
    def test_foo(self):
        with unittest.mock.patch('my_second_file.call'):
            self.assertEqual(Foo().foo(), "ok")

if __name__ == '__main__':
    unittest.main()

No właśnie tego się obawiałem :/ Nie mogę swobodnie zmienić implementacji bo testy zbyt dużo wiedzą o tej funkcji :/

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0