-
Notifications
You must be signed in to change notification settings - Fork 28
Update similarity.py to improve test coverage to 99% #295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
FanwangM
merged 5 commits into
theochem:main
from
mohini-aggarwal:update-similarity-94-coverage
Apr 14, 2026
+155
−0
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
d9faae3
Update similarity.py to improve test coverage to 94%
mohini-aggarwal 8f4446c
Fixed Formatting in similarity.py
mohini-aggarwal b63a7f3
Enhance similarity module test suite: refactor tests and increase cov…
mohini-aggarwal 45da470
Update similarity.py
mohini-aggarwal ee5b7cf
Fix test assertions and improve similarity test coverage
mohini-aggarwal File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| # -*- coding: utf-8 -*- | ||
| # | ||
| # The Selector is a Python library of algorithms for selecting diverse | ||
| # subsets of data for machine-learning. | ||
| # | ||
| # Copyright (C) 2022-2024 The QC-Devs Community | ||
| # | ||
| # This file is part of Selector. | ||
| # | ||
| # Selector is free software; you can redistribute it and/or | ||
| # modify it under the terms of the GNU General Public License | ||
| # as published by the Free Software Foundation; either version 3 | ||
| # of the License, or (at your option) any later version. | ||
| # | ||
| # Selector is distributed in the hope that it will be useful, | ||
| # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| # GNU General Public License for more details. | ||
| # | ||
| # You should have received a copy of the GNU General Public License | ||
| # along with this program; if not, see <http://www.gnu.org/licenses/> | ||
| # | ||
| # -- | ||
| """Test Similarity Module.""" | ||
|
|
||
| import numpy as np | ||
| import pytest | ||
|
|
||
| from selector.measures.similarity import ( | ||
| pairwise_similarity_bit, | ||
| tanimoto, | ||
| modified_tanimoto, | ||
| scaled_similarity_matrix, | ||
| similarity_index, | ||
| ) | ||
|
|
||
|
|
||
| def test_tanimoto_value(): | ||
| """Check correctness of Tanimoto similarity formula.""" | ||
| a = np.array([1, 0, 1]) | ||
| b = np.array([1, 1, 0]) | ||
| result = tanimoto(a, b) | ||
| assert pytest.approx(result) == 1 / 3 | ||
|
|
||
|
|
||
| def test_tanimoto_error(): | ||
| """Check tanimoto raises error for invalid input format.""" | ||
| with pytest.raises(ValueError): | ||
| tanimoto(np.array([[1, 2]]), np.array([1, 2])) | ||
|
|
||
|
|
||
| def test_tanimoto_shape_mismatch(): | ||
| """Check tanimoto raises error when vector shapes differ.""" | ||
| with pytest.raises(ValueError): | ||
| tanimoto(np.array([1, 2]), np.array([1, 2, 3])) | ||
|
|
||
|
|
||
| def test_modified_all_zero(): | ||
| """Check modified tanimoto handles zero vectors safely.""" | ||
| a = np.zeros(5) | ||
| b = np.zeros(5) | ||
| result = modified_tanimoto(a, b) | ||
| assert isinstance(result, (float, np.floating)) | ||
|
|
||
|
mohini-aggarwal marked this conversation as resolved.
|
||
|
|
||
| def test_modified_partial_case(): | ||
| """Check modified tanimoto returns valid float for partial overlap.""" | ||
| a = np.array([1, 0, 1, 0]) | ||
| b = np.array([1, 1, 0, 0]) | ||
| result = modified_tanimoto(a, b) | ||
| assert isinstance(result, (float, np.floating)) | ||
|
|
||
|
mohini-aggarwal marked this conversation as resolved.
|
||
|
|
||
| def test_invalid_metric(): | ||
| """Check pairwise_similarity_bit rejects invalid metric name.""" | ||
| X = np.array([[1, 0], [0, 1]]) | ||
| with pytest.raises(ValueError): | ||
| pairwise_similarity_bit(X, "wrong") | ||
|
|
||
|
|
||
| def test_pairwise_similarity_valid(): | ||
| """Check pairwise similarity returns correct matrix shape.""" | ||
| X = np.array([[1, 0], [0, 1]]) | ||
| result = pairwise_similarity_bit(X, "tanimoto") | ||
| assert result.shape == (2, 2) | ||
|
|
||
|
|
||
| def test_pairwise_invalid_dimension(): | ||
| """Check pairwise_similarity_bit rejects 1D input.""" | ||
| X = np.array([1, 0, 1]) | ||
| with pytest.raises(ValueError): | ||
| pairwise_similarity_bit(X, "tanimoto") | ||
|
|
||
|
|
||
| def test_scaled_identity(): | ||
| """Check scaled similarity preserves identity matrix.""" | ||
| X = np.eye(3) | ||
| assert np.allclose(scaled_similarity_matrix(X), X) | ||
|
|
||
|
|
||
| def test_scaled_general_case(): | ||
| """Check scaled similarity preserves matrix shape.""" | ||
| X = np.array([[2.0, 1.0], [1.0, 3.0]]) | ||
| result = scaled_similarity_matrix(X) | ||
| assert result.shape == X.shape | ||
|
|
||
|
|
||
| def test_scaled_not_square(): | ||
| """Check scaled similarity rejects non-square matrix.""" | ||
| X = np.array([[1, 2, 3], [4, 5, 6]]) | ||
| with pytest.raises(ValueError): | ||
| scaled_similarity_matrix(X) | ||
|
|
||
|
|
||
| def test_scaled_invalid_values(): | ||
| """Check scaled similarity rejects invalid diagonal values.""" | ||
| X = np.array([[0, 1], [1, 2]]) | ||
| with pytest.raises(ValueError): | ||
| scaled_similarity_matrix(X) | ||
|
|
||
|
|
||
| def test_similarity_invalid(): | ||
| """Check similarity_index rejects invalid method name.""" | ||
| x = np.array([1, 0]) | ||
| y = np.array([0, 1]) | ||
| with pytest.raises(ValueError): | ||
| similarity_index(x, y, "bad") | ||
|
|
||
|
|
||
| def test_similarity_shape_mismatch(): | ||
| """Check similarity_index rejects mismatched vector shapes.""" | ||
| x = np.array([1, 0, 1]) | ||
| y = np.array([1, 0]) | ||
| with pytest.raises(ValueError): | ||
| similarity_index(x, y, "RR") | ||
|
|
||
|
|
||
| def test_similarity_dimension_error(): | ||
| """Check similarity_index rejects 2D input.""" | ||
| x = np.array([[1, 0]]) | ||
| y = np.array([1, 0]) | ||
| with pytest.raises(ValueError): | ||
| similarity_index(x, y, "RR") | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| "idx", | ||
| ["AC", "BUB", "CT1", "CT2", "Fai", "Gle", "Ja", "JT", "RT", "RR", "SM", "SS1", "SS2"] | ||
| ) | ||
| def test_similarity_all_indices(idx): | ||
| """Check all similarity index methods return float.""" | ||
| x = np.array([1, 0, 1]) | ||
| y = np.array([1, 1, 0]) | ||
| result = similarity_index(x, y, idx) | ||
| assert isinstance(result, (float, np.floating)) | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.