12
12
# See the License for the specific language governing permissions and
13
13
# limitations under the License.
14
14
15
- import typing
16
-
17
15
import pandas as pd
18
16
import pytest
19
17
@@ -112,29 +110,20 @@ def empty_bf_df(
112
110
return session .read_pandas (empty_pandas_df )
113
111
114
112
115
- def mock_execute_total_rows_is_none (self , schema , * args , ** kwargs ):
116
- """Mocks an execution result where the total row count is missing."""
117
- from bigframes .session .executor import ExecuteResult
118
-
119
- return ExecuteResult (
120
- iter ([]), # arrow_batches
121
- schema = schema ,
122
- query_job = None ,
123
- total_bytes = None ,
124
- total_rows = None , # The specific failure condition for this case
125
- )
126
-
127
-
128
- def mock_execute_batches_are_invalid (self , schema , * args , ** kwargs ):
129
- """Mocks an execution result where the batch data is an invalid type."""
113
+ def mock_execute_result_with_params (
114
+ self , schema , total_rows_val , arrow_batches_val , * args , ** kwargs
115
+ ):
116
+ """
117
+ Mocks an execution result with configurable total_rows and arrow_batches.
118
+ """
130
119
from bigframes .session .executor import ExecuteResult
131
120
132
121
return ExecuteResult (
133
- None , # Invalid type for arrow_batches, which should be an iterator
122
+ iter ( arrow_batches_val ),
134
123
schema = schema ,
135
124
query_job = None ,
136
125
total_bytes = None ,
137
- total_rows = 100 , # A valid row count, as the error is in the batch data
126
+ total_rows = total_rows_val ,
138
127
)
139
128
140
129
@@ -475,25 +464,27 @@ def test_widget_row_count_should_be_immutable_after_creation(
475
464
"""
476
465
from bigframes .display import TableWidget
477
466
467
+ # Use a context manager to ensure the option is reset
478
468
with bf .option_context ("display.repr_mode" , "anywidget" , "display.max_rows" , 2 ):
479
469
widget = TableWidget (paginated_bf_df )
480
470
initial_row_count = widget .row_count
481
- assert initial_row_count == EXPECTED_ROW_COUNT
482
471
483
472
# Change a global option that could influence row count
484
473
bf .options .display .max_rows = 10
485
474
486
- # The widget's row count was fixed at creation and should not change .
475
+ # Verify the row count remains immutable .
487
476
assert widget .row_count == initial_row_count
488
477
489
478
490
479
@pytest .mark .parametrize (
491
- "mock_function " ,
480
+ "total_rows_param, arrow_batches_param " ,
492
481
[
493
- mock_execute_total_rows_is_none ,
494
- mock_execute_batches_are_invalid ,
482
+ # Corresponds to mock_execute_total_rows_is_none
483
+ (None , []),
484
+ # Corresponds to mock_execute_batches_are_invalid (assuming empty list
485
+ # for invalid batches for now)
486
+ (100 , []),
495
487
],
496
- # 'ids' provides descriptive names for each test run in the pytest report.
497
488
ids = [
498
489
"when_total_rows_is_None" ,
499
490
"when_arrow_batches_are_invalid" ,
@@ -502,65 +493,54 @@ def test_widget_row_count_should_be_immutable_after_creation(
502
493
def test_widget_should_fallback_to_zero_rows_on_error (
503
494
paginated_bf_df : bf .dataframe .DataFrame ,
504
495
monkeypatch : pytest .MonkeyPatch ,
505
- mock_function ,
496
+ total_rows_param ,
497
+ arrow_batches_param ,
506
498
):
507
499
"""
508
500
Given an internal component fails to return valid execution data,
509
501
when the TableWidget is created, its row_count should safely fall back to 0.
510
502
"""
511
- # The 'self' argument is automatically handled when monkeypatch calls the method.
512
- # We use a lambda to pass the DataFrame's schema to our mock function.
503
+ # Patch the executor's 'execute' method to simulate an error.
513
504
monkeypatch .setattr (
514
505
"bigframes.session.bq_caching_executor.BigQueryCachingExecutor.execute" ,
515
- lambda self , * args , ** kwargs : mock_function (
516
- self , paginated_bf_df ._block .expr .schema , * args , ** kwargs
506
+ lambda self , * args , ** kwargs : mock_execute_result_with_params (
507
+ self ,
508
+ paginated_bf_df ._block .expr .schema ,
509
+ total_rows_param ,
510
+ arrow_batches_param ,
511
+ * args ,
512
+ ** kwargs
517
513
),
518
514
)
519
515
516
+ # Create the TableWidget under the error condition.
520
517
with bf .option_context ("display.repr_mode" , "anywidget" ):
521
518
from bigframes .display import TableWidget
522
519
523
520
# The widget should handle the faulty data from the mock without crashing.
524
521
widget = TableWidget (paginated_bf_df )
525
522
526
- # The key assertion: The widget safely defaults to 0 rows.
523
+ # The widget safely defaults to 0 rows.
527
524
assert widget .row_count == 0
528
525
529
526
530
- @pytest .mark .parametrize (
531
- "max_results, expected_rows" ,
532
- [
533
- (None , EXPECTED_ROW_COUNT ),
534
- (3 , 3 ),
535
- (10 , EXPECTED_ROW_COUNT ),
536
- ],
537
- ids = ["no_limit" , "limit_is_less_than_total" , "limit_is_greater_than_total" ],
538
- )
539
- def test_widget_row_count_should_respect_max_results_on_creation (
527
+ def test_widget_row_count_reflects_actual_data_available (
540
528
paginated_bf_df : bf .dataframe .DataFrame ,
541
- max_results : typing .Optional [int ],
542
- expected_rows : int ,
543
529
):
544
530
"""
545
- Given a max_results value, when a TableWidget is created with custom batches ,
546
- its row_count should be correctly capped by that value .
531
+ Test that widget row_count reflects the actual data available ,
532
+ regardless of theoretical limits .
547
533
"""
548
- with bf .option_context ("display.repr_mode" , "anywidget" , "display.max_rows" , 2 ):
549
- from bigframes .core .blocks import PandasBatches
550
- from bigframes .display import TableWidget
534
+ from bigframes .display import TableWidget
551
535
536
+ # Set up display options that define a page size.
537
+ with bf .option_context ("display.repr_mode" , "anywidget" , "display.max_rows" , 2 ):
552
538
widget = TableWidget (paginated_bf_df )
553
539
554
- # Override batches with max_results to test the behavior
555
- widget ._batches = paginated_bf_df .to_pandas_batches (
556
- page_size = widget .page_size , max_results = max_results
557
- )
558
-
559
- # Re-apply the logic to update row_count
560
- if isinstance (widget ._batches , PandasBatches ):
561
- widget .row_count = widget ._batches .total_rows or 0
562
-
563
- assert widget .row_count == expected_rows
540
+ # The widget should report the total rows in the DataFrame,
541
+ # not limited by page_size (which only affects pagination)
542
+ assert widget .row_count == EXPECTED_ROW_COUNT
543
+ assert widget .page_size == 2 # Respects the display option
564
544
565
545
566
546
# TODO(shuowei): Add tests for custom index and multiindex
0 commit comments