Skip to content

Commit

Permalink
Modify test macro to test for multiple warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
FlickerSoul committed Jul 22, 2024
1 parent 5d7a29e commit 53897de
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 50 deletions.
30 changes: 13 additions & 17 deletions src/tests/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ mod inner {

#[macro_export]
macro_rules! py_expect_warning {
($py:expr, $($val:ident)+, $code:expr, $warning_msg:literal) => {{
($py:expr, $($val:ident)+, $code:expr, [$(($warning_msg:literal, $warning_category:path)),+] $(,)?) => {{
use pyo3::types::IntoPyDict;
let d = [$((stringify!($val), $val.to_object($py)),)+].into_py_dict_bound($py);
py_expect_warning!($py, *d, $code, $warning_msg)
py_expect_warning!($py, *d, $code, [$(($warning_msg, $warning_category)),+])
}};
($py:expr, *$dict:expr, $code:expr, $warning_msg:literal) => {{
($py:expr, *$dict:expr, $code:expr, [$(($warning_msg:literal, $warning_category:path)),+] $(,)?) => {{
let code_lines: Vec<&str> = $code.lines().collect();
let indented_code: String = code_lines.iter()
.map(|line| format!(" {}", line)) // add 4 spaces indentation
Expand All @@ -83,22 +83,18 @@ with warnings.catch_warnings(record=True) as warning_record:
"#, indented_code);

$py.run_bound(wrapped_code.as_str(), None, Some(&$dict.as_borrowed())).expect("Failed to run warning testing code");
let warning_record = $dict.get_item("warning_record").expect("Failed to capture warnings").expect("Failed to downcast to PyList");
let warning = warning_record.get_item(0).expect("No warnings captured");
let expected_warnings = [$(($warning_msg, <$warning_category as pyo3::PyTypeInfo>::type_object_bound($py))),+];
let warning_record: Bound<'_, pyo3::types::PyList> = $dict.get_item("warning_record").expect("Failed to capture warnings").expect("Failed to downcast to PyList").extract().unwrap();

let actual_warning_msg: String = warning.getattr("message").unwrap().getattr("args").unwrap().get_item(0).unwrap().extract().expect("Failed to extract warning message");
assert_eq!(actual_warning_msg, $warning_msg.to_string());
assert_eq!(warning_record.len(), expected_warnings.len(), "Expecting {} warnings but got {}", expected_warnings.len(), warning_record.len());

warning
}};
($py:expr, $($val:ident)+, $code:expr, $warning_msg:literal, $warning_category:path) => {{
let warning = py_expect_warning!($py, $($val)+, $code, $warning_msg);
let actual_category = warning.getattr("category").unwrap();
let expected_category = <$warning_category as pyo3::PyTypeInfo>::type_object_bound($py);
let is_same_category = expected_category.clone().is_subclass(&actual_category).unwrap_or(false);
assert!(is_same_category, "Expected warning category {:?} but got {:?}", expected_category, actual_category);

warning
for ((index, warning), (msg, category)) in warning_record.iter().enumerate().zip(expected_warnings.iter()) {
let actual_msg = warning.getattr("message").unwrap().str().unwrap().to_string_lossy().to_string();
let actual_category = warning.getattr("category").unwrap();

assert_eq!(actual_msg, msg.to_string(), "Warning message mismatch at index {}, expecting `{}` but got `{}`", index, msg, actual_msg);
assert!(actual_category.is(category), "Warning category mismatch at index {}, expecting {:?} but got {:?}", index, category, actual_category);
}
}};
}

Expand Down
42 changes: 16 additions & 26 deletions tests/test_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,98 +1234,87 @@ fn test_pymethods_warn() {
py,
obj,
"obj.method_with_warning()",
"this method raises warning",
PyUserWarning
[("this method raises warning", PyUserWarning)],
);

// FnType::Fn
py_expect_warning!(
py,
obj,
"obj.method_with_warning_and_custom_category()",
"this method raises warning",
PyFutureWarning
[("this method raises warning", PyFutureWarning)]
);

// #[staticmethod], FnType::FnStatic
py_expect_warning!(
py,
typeobj,
"typeobj.static_method()",
"this static method raises warning",
PyUserWarning
[("this static method raises warning", PyUserWarning)]
);

// #[classmethod], FnType::FnClass
py_expect_warning!(
py,
typeobj,
"typeobj.class_method()",
"this class method raises warning",
PyUserWarning
[("this class method raises warning", PyUserWarning)]
);

// #[classmethod], FnType::FnClass
py_expect_warning!(
py,
obj,
"obj.class_method()",
"this class method raises warning",
PyUserWarning
[("this class method raises warning", PyUserWarning)]
);

// #[new], FnType::FnNew
py_expect_warning!(
py,
typeobj,
"typeobj()",
"this __new__ method raises warning",
PyUserWarning
[("this __new__ method raises warning", PyUserWarning)]
);

// #[getter], FnType::Getter
py_expect_warning!(
py,
obj,
"val = obj.value",
"this getter raises warning",
PyUserWarning
[("this getter raises warning", PyUserWarning)]
);

// #[setter], FnType::Setter
py_expect_warning!(
py,
obj,
"obj.value = 10",
"this setter raises warning",
PyUserWarning
[("this setter raises warning", PyUserWarning)]
);

// PyMethodProtoKind::Slot
py_expect_warning!(
py,
obj,
"obj[0]",
"this subscript op method raises warning",
PyUserWarning
[("this subscript op method raises warning", PyUserWarning)]
);

// PyMethodProtoKind::SlotFragment
py_expect_warning!(
py,
obj,
"obj + obj",
"the + op method raises warning",
PyUserWarning
[("the + op method raises warning", PyUserWarning)]
);

// PyMethodProtoKind::Call
py_expect_warning!(
py,
obj,
"obj()",
"this __call__ method raises warning",
PyUserWarning
[("this __call__ method raises warning", PyUserWarning)]
);
});

Expand All @@ -1350,8 +1339,10 @@ fn test_pymethods_warn() {
py,
typeobj,
"typeobj()",
"this class-method __new__ method raises warning",
PyUserWarning
[(
"this class-method __new__ method raises warning",
PyUserWarning
)]
);
});
}
Expand Down Expand Up @@ -1381,8 +1372,7 @@ fn test_pymethods_deprecated() {
py,
obj,
"obj.deprecated_method()",
"this method is deprecated",
PyDeprecationWarning
[("this method is deprecated", PyDeprecationWarning)]
);
});
}
22 changes: 15 additions & 7 deletions tests/test_pyfunction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,12 @@ fn test_pyfunction_warn() {

Python::with_gil(|py| {
let f = wrap_pyfunction_bound!(function_with_warning)(py).unwrap();
py_expect_warning!(py, f, "f()", "this function raises warning", PyUserWarning);
py_expect_warning!(
py,
f,
"f()",
[("this function raises warning", PyUserWarning)]
);
});

#[pyfunction]
Expand All @@ -626,8 +631,10 @@ fn test_pyfunction_warn() {
py,
f,
"f()",
"this function raises warning with category",
PyFutureWarning
[(
"this function raises warning with category",
PyFutureWarning
)]
);
});

Expand All @@ -641,8 +648,10 @@ fn test_pyfunction_warn() {
py,
f,
"f()",
"custom deprecated category",
pyo3::exceptions::PyDeprecationWarning
[(
"custom deprecated category",
pyo3::exceptions::PyDeprecationWarning
)]
);
});
}
Expand All @@ -659,8 +668,7 @@ fn test_pyfunction_deprecated() {
py,
f,
"f()",
"this function is deprecated",
PyDeprecationWarning
[("this function is deprecated", PyDeprecationWarning)]
);
});
}

0 comments on commit 53897de

Please sign in to comment.