How to monkeypatch Path().exists() - pytest

How would you monkeypatch using the pytest framework the
Path('folder/file.suffix').exists()
?
This is the how to do it with OS library
from _pytest.monkeypatch import MonkeyPatch
monkeypatch = MonkeyPatch()
monkeypatch.setattr(os.path, "exists", lambda _: True)

Related

Unable to pass mocked fixture as an argument in parametrized tests in pytest

See below, is it even possible to pass a mock fixture (mock_adam, "adam", "0.001", ...) in parametrized tests for reusability purposes?
import pytest
from contextlib import contextmanager
from unittest import mock
from my_module import get_optimizer
#contextmanager
def does_not_raise():
yield
#pytest.fixture(autouse=True)
def mock_adam():
with mock.patch("my_module.optimizers.Adam") as mocker:
yield mocker
#pytest.fixture(autouse=True)
def mock_RMSprop():
with mock.patch("my_module.optimizers.RMSprop") as mocker:
yield mocker
class TestGetOptimizers:
#pytest.mark.parametrize(
"mock_optimizer, optimizer_name, learning_rate, clipnorm, expectation",
[
(mock_adam, "adam", "0.001", "1.1", does_not_raise()),
(mock_RMSprop, "rmsprop", "0.001", "1.1", does_not_raise()),
],
)
def test_get_optimizer(self, mock_optimizer, optimizer_name, learning_rate, clipnorm, expectation):
with expectation:
get_optimizer(
optimizer_name=optimizer_name,
learning_rate=learning_rate,
clipnorm=clipnorm,
)
mock_optimizer.assert_called_once_with(lr=learning_rate, clipnorm=clipnorm)
AttributeError: 'function' object has no attribute 'assert_called_once_with'
To achieve this, you can create a single fixture that would get the path to mock as an indirect parameter, like so:
import pytest
from contextlib import contextmanager
from unittest import mock
from my_module import get_optimizer
#contextmanager
def does_not_raise():
yield
#pytest.fixture
def mock_with_param(request):
with mock.patch(request.param) as mocker:
yield mocker
class TestGetOptimizers:
#pytest.mark.parametrize(
"mock_with_param, optimizer_name, learning_rate, clipnorm, expectation",
[
("my_module.optimizers.Adam", "adam", "0.001", "1.1", does_not_raise()),
("my_module.optimizers.RMSprop", "rmsprop", "0.001", "1.1", does_not_raise()),
], indirect=["mock_with_param"]
)
def test_get_optimizer(self, mock_with_param, optimizer_name, learning_rate, clipnorm, expectation):
with expectation:
get_optimizer(
optimizer_name=optimizer_name,
learning_rate=learning_rate,
clipnorm=clipnorm,
)
mock_with_param.assert_called_once_with(lr=learning_rate, clipnorm=clipnorm)

the tkinter button does not work in ubuntu

I can't make the button work, it works as it should on the windows, why doesn't it work in ubuntu?
import tkinter as tk
from tkinter import ttk
import sys
class Application(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.attributes("-alpha", 1)
self.attributes("-topmost", True)
self.overrideredirect(True)
self.resizable(False, False)
self.title("CPU-RAM usage monitor bar")
self.set_ui()
def set_ui(self):
exit_but = tk.Button(self, text="Exit", command=lambda: self.app_exit)
exit_but.pack(fill=tk.X)
def app_exit(self):
self.destroy()
sys.exit()
root = Application()
root.mainloop()

pytest - mockup a complex module import

I have found several posts on how to "hide" a package and simulate an ImportError with pytest, however, I haven't succeeded in my case and I am looking for some help:
Test for import of optional dependencies in __init__.py with pytest: Python 3.5 /3.6 differs in behaviour
Test behavior of code if optional module is not installed
and related
Here is the content of an __about__.py file that I want to test with pytest.
"""Get the metadata from the package or from setup.py."""
try:
import importlib
metadata = importlib.metadata
except ImportError:
import importlib_metadata as metadata
try:
data = metadata.metadata("mypackage")
__version__ = data["Version"]
__author__ = data["Author"]
__name__ = data["Name"]
except metadata.PackageNotFoundError:
# The repo of the package is accessible to python to get at least the version
import re
from pathlib import Path
try:
from nested_grid_plotter import __file__ as loc
with open(Path(loc).parent.joinpath("../setup.py"), "r") as f:
data = f.read()
except FileNotFoundError:
data = ""
def version_parser(v):
"""Parse the version from the setup file."""
version_pattern = (
r"""(version\s*=\s*)["|'](\d+(=?\.(\d+(=?\.(\d+)*)*)*)*)["|']"""
)
regex_matcher = re.compile(version_pattern).search(v)
if regex_matcher is None:
return "unknwon"
return regex_matcher.group(2)
try:
__version__ = version_parser(data)
except Exception:
__version__ = "unknown"
__author__ = "unknown"
__name__ = "unknown"
Here is the __init__.py at the root of the package:
from .__about__ import __version__, __name__, __author__
And here is the tests that I have come up with until now. However, I am not able to hide importlib.
"""Test the file __about__.py."""
import pytest
import sys
class PackageDiscarder:
def __init__(self):
self.pkgnames = []
def find_spec(self, fullname, path, target=None):
if fullname in self.pkgnames:
raise ImportError()
#pytest.fixture
def no_requests():
sys.modules.pop("importlib", None)
d = PackageDiscarder()
d.pkgnames.append("importlib")
sys.meta_path.insert(0, d)
yield
sys.meta_path.remove(d)
#pytest.fixture(autouse=True)
def cleanup_imports():
yield
sys.modules.pop("mypackage", None)
def test_requests_available():
import mypackage
assert mypackage.__version__ != "unknwon"
#pytest.mark.usefixtures("no_requests")
def test_requests_missing():
import mypackage
assert mypackage.__version__ != "unknwon"
Here is the coverage report:
Name Stmts Miss Cover Missing
----------------------------------------------------------------
mypackage/__about__.py 31 10 68% 5-6, 10-12, 23-24, 33, 38-39
----------------------------------------------------------------
TOTAL 31 10 68%

Patches in scalatest

I'm new to scala and same for scalatest.
My aim is to write a Unit test for the following small piece of code:
import java.sql.SQLException
import com.typesafe.scalalogging.LazyLogging
import slick.jdbc.MySQLProfile.api._
import scala.concurrent.{ExecutionContext, ExecutionContextExecutor, Future}
object DbCreator extends LazyLogging {
implicit val ex: ExecutionContextExecutor = ExecutionContext.global
def createDatabaseIfNotExist(): Future[String] = {
Database
.forURL(url = "some host", user = "user", password = "pass", driver = "driver")
.run(sqlu"CREATE DATABASE ...").map(_ => "created")
.recover {
case e: Throwable => {
logger.error("Error!", e)
throw new SQLException(e.getMessage)
}
}
}
}
I've previously used python, which has the patch concept.
So my idea was to patch the Database class being imported and used in createDatabaseIfNotExist, so I can verify the different scenarios.
Unfortunately, I could not find equivalent/similar concept in scalatest.
Did I miss it?
Is my approach wrong? If so, how would u suggest me write a UT for the createDatabaseIfNotExist method?
Is the current DbCreator implementation not testable enough?
Many thanks for all help!
I see several options:
scalamock or some java mocking library
acolyte JDBC driver (has scala DSL)
embedded mysql

Scala headOption not found

I migrated my Play version from 2.3 to 2.4. In my previous version I used firstOption to get the latest record from DB. But that functionality is removed in latest version of slick. I searched and found that we can use headOption instead of firstOption. The following is my code :
def findById(id: String)(implicit ec: ExecutionContext): Future[Option[Client]] =
Future {
DB.withConnection { implicit session =>
Clients.filter(c => c.id === id).firstOption
}
}
The imports I have used are as follows :
import play.api.Play.current
import play.api.db.DB
import slick.driver.PostgresDriver.api._
import scala.concurrent.{ExecutionContext, Future}
When I tried to replace firstOption with headOption it shows error 'cannot resolve symbol headOption'. Am I missing any import statements? Is there any alternative way to fix this?
Try
Clients.filter(c => c.id === id).result.headOption
Your object structure is not clear to me but the way I use it is:
val query = tableInstance.filter(_.id === id)
val action = query.result.headOption
db.run(action)
where tableInstance is of slick's TableQuery type
Try to import
scala.collections.convert.WrapAsScala._
This solved the problem on my side.