Skip to content

Data Science Template: implement expect_csv_output test function #339

Description

@ArthurCRodrigues

Parent Issue

Part of #338 — Feature: Data Science Template (data_science)


Overview

Implement the expect_csv_output test function that executes the student's program and validates a generated CSV file against expected structure and values. This is the primary test for assignments where students produce tabular data outputs (DataFrames exported to CSV).


Interface

class ExpectCsvOutputTest(BaseExecutionTest):
    @property
    def name(self):
        return "expect_csv_output"

Parameters

Parameter Type Required Description
program_command string/dict Command to execute the student's script. Supports multi-language dict format and "CMD" auto-resolution.
artifact_path string Relative path to the generated CSV file (e.g., output.csv). Extracted from sandbox /app/ directory.
expected_columns list[string] Expected column names. Comparison is order-insensitive.
expected_shape [int, int] Expected [rows, columns] shape of the CSV.
expected_values dict Column → list of expected values for spot-checking specific cells.
tolerance float Numeric tolerance for value comparison (default: 0.001).
sort_by string Column to sort by before comparison (handles non-deterministic row order).
inputs list[string] Stdin inputs if the program requires interactive input.

Scoring Logic

The test performs multiple independent checks. Scoring works as follows:

  1. File existence — If the artifact file is not found in the sandbox after execution, score is 0.
  2. CSV parsing — If the file exists but cannot be parsed as valid CSV, score is 0.
  3. Column check (if expected_columns specified):
    • Score proportional to the number of correct columns found: (matched_columns / expected_columns) * weight_of_this_check
    • Extra columns in the student output are ignored (not penalized).
  4. Shape check (if expected_shape specified):
    • Binary: 0 if shape doesn't match, full credit if it does.
  5. Value check (if expected_values specified):
    • Score proportional to matching values within tolerance.
    • For numeric values: abs(actual - expected) <= tolerance → match.
    • For string values: exact match after strip.

If multiple checks are specified, the final score is the weighted average (equal weights across active checks).

If ALL specified checks pass → 100. If none specified beyond artifact_path → 100 (file existence only).


Execution Flow

  1. Run program_command in the sandbox (via run_sandbox_execution from BaseExecutionTest).
  2. Check for base errors (timeout, compilation error, runtime error) → score 0 with appropriate message.
  3. Extract file at /app/{artifact_path} from the sandbox using sandbox.extract_file().
  4. Parse CSV content using Python's csv.reader (NOT pandas — the autograder should not depend on pandas).
  5. If sort_by specified, sort rows by that column before comparison.
  6. Run each active check and compute final score.

Error Handling

Scenario Result
Program times out Score 0, report timeout message
Program crashes (runtime error) Score 0, report error
File not found after execution Score 0, report "file not generated"
File is not valid CSV Score 0, report "invalid CSV format"
Column mismatch Partial score with details of missing columns
Shape mismatch Score 0 for shape check, report expected vs actual
Value mismatch Partial score, report which values didn't match

Example Usage

{
  "name": "expect_csv_output",
  "parameters": {
    "program_command": "python3 analysis.py preprocess",
    "artifact_path": "cleaned.csv",
    "expected_columns": ["name", "cuisine", "rating", "price_range", "city"],
    "expected_shape": [1420, 5],
    "sort_by": "name",
    "tolerance": 0.01
  },
  "weight": 50
}

Implementation Notes

  • Inherit from BaseExecutionTest (defined in input_output.py) to reuse run_sandbox_execution and check_for_base_errors.
  • Use sandbox.extract_file(f"/app/{artifact_path}") to get file content (same pattern as ExpectFileArtifactTest).
  • Parse CSV with csv.reader from stdlib — no external dependencies.
  • Numeric detection: attempt float() conversion; if it succeeds, compare with tolerance; otherwise, string compare.
  • Validate artifact_path for path traversal (reject .. and absolute paths) — reuse ExpectFileArtifactTest._validate_artifact_path logic.
  • All user-facing messages must go through the t() translation function.

Translation Keys Needed

  • data_science.expect_csv_output.description
  • data_science.expect_csv_output.report.success
  • data_science.expect_csv_output.report.file_not_found
  • data_science.expect_csv_output.report.invalid_csv
  • data_science.expect_csv_output.report.column_mismatch
  • data_science.expect_csv_output.report.shape_mismatch
  • data_science.expect_csv_output.report.value_mismatch
  • data_science.expect_csv_output.report.partial_success

Acceptance Criteria

  • Test function registered in DataScienceTemplate.tests dict with key "expect_csv_output"
  • Passes when student generates correct CSV matching all specified checks
  • Fails with informative message when file is not generated
  • Fails with informative message when CSV is malformed
  • Partial scoring works correctly for column/value checks
  • Tolerance-based numeric comparison works
  • sort_by correctly normalizes row order before comparison
  • Path traversal in artifact_path is rejected
  • Unit tests cover all success/failure scenarios with mocked sandbox
  • Translation keys added for pt-BR and en

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions