-
Notifications
You must be signed in to change notification settings - Fork 0
Adds test coverage for drag&drop functionality #13
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
base: main
Are you sure you want to change the base?
Conversation
This commit introduces a suite of tests for the drag and drop functionality
in `sub_plot_widget.py`. The tests cover the following scenarios:
1. Dragging a new data item (e.g., from a variable list) onto a
SubPlotWidget to create a new trace.
2. Reordering an existing trace (CustomPlotItem) within the same
SubPlotWidget by dragging its label.
3. Moving an existing trace from one SubPlotWidget to another. This
includes verifying that signal connections for time synchronization
are updated.
4. Dragging a trace label onto the main plot area (not the label area)
of the same SubPlotWidget, which should append it to the end of the
trace list.
5. Attempting to drag items with unrecognized mime types, ensuring these
are correctly ignored by the SubPlotWidget.
Helper functions for creating mock Qt drag/drop events, mime data, and
for common test setup and assertion patterns have been added to
`tests/test_sub_plot_widget.py` to support these tests and improve
maintainability.
This commit refactors the drag and drop tests for SubPlotWidget in `tests/test_sub_plot_widget.py` to utilize `pytest-qt` more thoroughly for event simulation. Key changes include: - Modified `custom_plot_item.py` to make `CustomPlotItem` instances genuinely draggable by implementing `mousePressEvent` and `mouseMoveEvent` to initiate a `QDrag` operation with appropriate mime data. - Introduced new mock draggable items (`MockDraggableVarItem`, `MockDraggableUnrecognizedItem`) in the test suite to simulate drag origins for different scenarios. These mocks also initiate `QDrag`. - All drag-and-drop test cases now use `qtbot.mousePress` and `qtbot.mouseMove` on these draggable items/widgets to start the drag operation. - `QDrag.exec_()` is mocked for these tests. The side_effect of this mock dispatches `QDragEnterEvent`, `QDragMoveEvent` (optional), and `QDropEvent` to the `SubPlotWidget` using `QApplication.sendEvent()`. The `source()` of these dispatched events is patched to ensure the target widget correctly identifies the drag originator. - Obsolete helper functions for manual event creation have been removed. Note: During execution in the automated environment, I encountered a "Fatal Python error: Aborted" during the `qapp` fixture initialization (part of `pytest-qt`). This prevented full verification of these refactored tests in that specific environment. The code has been structured for compatibility with a functional `pytest-qt` setup.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello @miker2, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!
Summary of Changes
Hello team,
Gemini here, providing a summary of this pull request authored by @miker2. The primary goal of this PR, as indicated by the title, is to add comprehensive test coverage for the drag-and-drop functionality within the application's plotting widgets, specifically focusing on the SubPlotWidget and CustomPlotItem components. The changes involve both minor adjustments to the existing drag handling code in custom_plot_item.py to improve testability and, more significantly, the addition of a new suite of tests in tests/test_sub_plot_widget.py to cover various drag-and-drop scenarios. The tests leverage pytest-qt and mocking techniques to simulate user interactions and verify the expected behavior.
Highlights
- Test Coverage: Adds extensive new test cases for the drag-and-drop features in
SubPlotWidget. - Drag & Drop Scenarios Tested: Includes tests for dragging new data items onto a subplot, reordering existing traces within a subplot, moving traces between different subplots, dragging traces to the plot area to append them, and verifying that drags with unrecognized mime types are ignored.
- Testing Framework: Utilizes
pytest-qt'sqtbotfor simulating GUI interactions andmockerfor patching methods likeQDrag.exec_to control the drag-and-drop flow in tests. - Code Adjustments: Makes minor adjustments to
CustomPlotItem's drag handling, such as initializing the drag start position as aQPointand usingself.grab()for the drag pixmap, primarily to facilitate testing. - Test Helpers: Introduces mock classes (
MockDraggableVarItem,MockDraggableUnrecognizedItem) and helper functions (_add_traces_to_subplot,_assert_trace_order_and_colors,create_data_item_mime_data,create_unrecognized_mime_data) to streamline test setup and verification.
Changelog
Click here to see the changelog
- custom_plot_item.py
- Added import for
QPointfromPyQt5.QtCore. - Adjusted the import of
QApplicationto directly import fromPyQt5.QtWidgetsand removed thetry...exceptblock. - Changed the initialization of
_drag_start_positionfromNonetoQPoint()and renamed the attribute todrag_start_position. - Updated
mousePressEventandmouseMoveEventto use the newself.drag_start_positionattribute. - Added checks in
mouseMoveEventto ensuredrag_start_positionis valid before initiating a drag. - Replaced
QPixmap(self.size())andself.render(pixmap)withself.grab()for creating the drag pixmap. - Cleaned up
try...exceptblocks around mime data setting anddrag.exec_()calls, adding logging outside the blocks. - Ensured
drag_start_positionis reset toQPoint()afterdrag.exec_().
- Added import for
- tests/test_sub_plot_widget.py
- Added necessary imports for Qt drag and drop testing classes (
QEvent,QDragEnterEvent,QDragMoveEvent,QDropEvent,QDrag,QMouseEvent,QApplication,QWidget,pickle). - Added a
var_nameattribute to theMockDataSourceclass. - Introduced
MockDraggableVarItemandMockDraggableUnrecognizedItemclasses to simulate different drag sources. - Added helper functions
_add_traces_to_subplotand_assert_trace_order_and_colorsfor test setup and assertions. - Added helper functions
create_data_item_mime_dataandcreate_unrecognized_mime_datafor creating mock mime data. - Removed obsolete event creation helper functions.
- Implemented new test functions using
qtbotandmockerto cover various drag-and-drop scenarios:test_drag_data_item_to_subplot,test_reorder_custom_plot_item_same_subplot,test_move_custom_plot_item_between_subplots,test_drag_custom_plot_item_to_plot_area_appends, andtest_drag_unrecognized_mime_type_is_ignored. - Updated existing test function definitions to include the
qtbotfixture.
- Added necessary imports for Qt drag and drop testing classes (
Using Gemini Code Assist
The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.
Invoking Gemini
You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.
| Feature | Command | Description |
|---|---|---|
| Code Review | /gemini review |
Performs a code review for the current pull request in its current state. |
| Pull Request Summary | /gemini summary |
Provides a summary of the current pull request in its current state. |
| Comment | @gemini-code-assist | Responds in comments when explicitly tagged, both in issue comments and review comments. |
| Help | /gemini help |
Displays a list of available commands. |
Customization
To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.
Limitations & Feedback
Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.
You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.
Drag a trace with ease,
Across the plot, if you please.
Tests now confirm,
No bugs will squirm,
GUI moves bring sweet release.
Footnotes
-
Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution. ↩
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces comprehensive test coverage for drag-and-drop functionality, which is a valuable addition. The new tests in tests/test_sub_plot_widget.py cover various scenarios, and the changes in custom_plot_item.py refine the drag-and-drop implementation. The use of qtbot and mocker are well-executed.
Summary of Findings
- Error Handling in
CustomPlotItem.mouseMoveEvent: Removed specifictry-exceptblocks around MIME data creation. Ifself.trace.name()returnsNone,self.trace.name().encode()will raise anAttributeError. This could lead to unhandled exceptions during drag operations. Suggests re-adding error handling or checks forNone. - Attribute Naming Convention (Minor/Not Commented): The attribute
_drag_start_positionwas changed todrag_start_position(public). If this change is primarily to facilitate testing, it's a common practice. However, if not strictly necessary for external access beyond testing, maintaining it as a protected member (_drag_start_position) would align better with encapsulation principles. This was not commented on due to review settings for severity.
Merge Readiness
The pull request significantly improves test coverage and is generally in good shape. However, I recommend addressing the high and medium-severity issues regarding error handling in custom_plot_item.py to ensure robustness during drag-and-drop operations. Once those points are considered, the PR should be in a strong position for merging. As a reviewer, I am not authorized to approve pull requests; please ensure further review and approval by authorized maintainers.
| # Set specific data for "application/x-customplotitem" format | ||
| # This is what SubPlotWidget's dropEvent will primarily check via hasFormat and then use text(). | ||
| # Encoding the trace name as QByteArray for setData. | ||
| mime_data.setData("application/x-customplotitem", self.trace.name().encode()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous version of this code had specific try-except blocks around mime_data.setText() and mime_data.setData() calls, logging errors if they occurred. The current refactoring has removed these.
If self.trace.name() were to return None (which PlotDataItem.name() can, as it returns self.opts.get('name', None)), then self.trace.name().encode() would raise an AttributeError ('NoneType' object has no attribute 'encode'). This could cause an unhandled exception during the drag operation, potentially crashing or destabilizing the drag. Can we consider adding a check for self.trace.name() being None or reintroducing a broader try-except block around the MIME data population to catch potential exceptions and log them, ensuring the drag operation fails gracefully or can be aborted cleanly?
if self.trace.name() is not None:
mime_data.setData("application/x-customplotitem", self.trace.name().encode())
else:
mime_data.setData("application/x-customplotitem", QByteArray())| mime_data = QMimeData() | ||
|
|
||
| # Set text for general purpose (e.g., if dropped on a text editor or for SubPlotWidget's text() check) | ||
| mime_data.setText(self.trace.name()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous version of this code had specific try-except blocks around mime_data.setText() and mime_data.setData() calls, logging errors if they occurred. The current refactoring has removed these.
If self.trace.name() were to return None (which PlotDataItem.name() can, as it returns self.opts.get('name', None)), then mime_data.setText(self.trace.name()) might pass None to Qt, which could lead to unexpected behavior or errors depending on Qt's handling of None for string conversion. Can we consider adding a check for self.trace.name() being None or reintroducing a broader try-except block around the MIME data population to catch potential exceptions and log them, ensuring the drag operation fails gracefully or can be aborted cleanly?
if self.trace.name() is not None:
mime_data.setText(self.trace.name())
else:
mime_data.setText("") # Or some default stringThis commit refactors the drag-and-drop (DND) tests for SubPlotWidget
in `tests/test_sub_plot_widget.py` to utilize `pytest-qt` more
thoroughly for event simulation.
Key changes include:
1. **Draggable `CustomPlotItem`:**
* I modified `custom_plot_item.py` to make `CustomPlotItem` instances
genuinely draggable. They now implement `mousePressEvent` and
`mouseMoveEvent` to initiate a `QDrag` operation with the
"application/x-customplotitem" mime type.
2. **Test Implementation with `pytest-qt`:**
* All DND tests now use `qtbot.mousePress` and `qtbot.mouseMove`
on the source items (either a `CustomPlotItem` or a new mock
draggable widget) to initiate drag operations.
* I introduced new mock widgets (`MockDraggableVarItem`,
`MockDraggableUnrecognizedItem`) to simulate
specific drag sources.
* `QDrag.exec_()` is consistently mocked. Its side_effect function
simulates the DND event sequence on the `SubPlotWidget` by
dispatching events (QDragEnterEvent, QDragMoveEvent, QDropEvent)
via `QApplication.sendEvent()`.
* I patched the `source()` method of these dispatched events to ensure
the `SubPlotWidget` correctly identifies the drag originator.
3. **Helper Function Cleanup:**
* I removed obsolete helper functions previously used for manual event
creation. Mime data creation helpers have been retained.
This approach makes the DND tests more realistic by having `qtbot`
drive user input and by making the application's `CustomPlotItem`
an active participant in the drag operation.
Note: I encountered a fatal Qt/pytest-qt setup error that hindered test execution in the remote environment. I'm providing these changes for your local testing and review.
No description provided.