Concepts / Evaluating Code Generation Benchmarks

Evaluating Code Generation Benchmarks

Functional correctness measures whether code performs its intended functionality, and it is treated as the ultimate metric for evaluating an application.

  • Programming

Why Running Code Beats Reading It

Suppose a model hands you a function that looks clean, well named, and sensible. It is tempting to conclude that the code is good. But when a model generates code, the first question is not whether the code looks reasonable. The question is whether it does what it was supposed to do. Answering that question requires a different kind of check than reading the code, and for code generation that check can often be performed automatically.

This article focuses on the code case, where functional correctness can be measured automatically. We will start with a concrete run of a checking program so you can see what a functional correctness report looks like, then build up the ideas behind it: what a test case is, how a harness decides between pass and fail, and how public benchmarks use the same idea to score AI systems.

Functional Correctness as the Ultimate Metric

Definition

Functional correctness measures whether code performs its intended functionality. It is treated as the ultimate metric for evaluating an application, because the purpose of an application is to do its job.

Functional correctness evaluation means evaluating a system based on whether it performs the intended functionality. The idea is not special to code. The same question applies to any system you ask a model to build or operate, and the check is always about the outcome the system is supposed to produce.

In the real world

If you ask a model to build a website, you check whether the website meets your requirements. If you ask it to make a restaurant reservation, you check whether the reservation succeeds. In both cases the judgment rests on the result the system delivers, not on how the underlying work appears.

Coding platforms apply the same logic. Functional correctness evaluation is how coding platforms like LeetCode and HackerRank validate submitted solutions, and long before AI was used to write code, automatically verifying functional correctness was standard practice in software engineering.

A Checking Program in Action

Consider a program that checks a generated gcd function against a list of input pairs, where each pair has an expected greatest common divisor. The program prints one result per pair, and it labels each mismatch with the expected value and the value the function actually produced. The function below is a deliberately flawed candidate, written for this lesson, that returns the smaller of its two inputs instead of computing the greatest common divisor. The harness runs it on four pairs.

python
Notes on the code
  • candidate_gcd is the generated function under test
  • Each tuple is one test case: two inputs followed by the expected result
  • The conditional expression chooses the label by comparing actual with expected
  • The print statement reports the input pair, the expected value, and the value produced

What do you think happens?

What lines does the harness print?

Reveal answer
Answer:

FAIL (12, 8): expected 4, got 8FAIL (15, 20): expected 5, got 15PASS (8, 4): expected 4, got 4FAIL (9, 6): expected 3, got 6

min returns the smaller input. For (12, 8) that is 8, but the greatest common divisor is 4. For (15, 20) it returns 15 instead of 5. For (8, 4) it returns 4, which happens to equal the correct answer, so that line passes. For (9, 6) it returns 6 instead of 3.

Reading the Report Line by Line

Read the report one line at a time. Each line beginning with FAIL names one input pair, then states the expected value and the value the function produced. A line such as FAIL (15, 20): expected 5, got 15 is a mismatch: the correct greatest common divisor of 15 and 20 is 5, so a function that returns anything other than 5 for that pair is wrong. The report shows exactly where the function diverged from the expected result, which is the information a developer needs in order to debug it.

Worked example

Tracing the FAIL line for (15, 20)

The harness reaches the test tuple (15, 20, 5). What exactly does it compute and print?

  1. 1
    Unpack the tuple

    The loop assigns a = 15, b = 20, and expected = 5.

  2. 2
    Run the candidate

    candidate_gcd(15, 20) evaluates min(15, 20), which is 15. So actual = 15.

  3. 3
    Compare

    actual == expected asks whether 15 equals 5. It does not, so the condition is False and status becomes 'FAIL'.

  4. 4
    Print

    The f-string fills in the pair (15, 20), the expected value 5, and the actual value 15, producing FAIL (15, 20): expected 5, got 15.

Result

The harness prints FAIL (15, 20): expected 5, got 15, which identifies the exact input where the function diverges.

The PASS line in the report deserves attention too. The pair (8, 4) passes only because the smaller input happens to be the greatest common divisor for that pair. One matching line is not evidence that the function is correct. A single successful check tells you about that one scenario, and nothing more.

Two Questions: Validity and Correctness

A measurement of functional correctness has two stages. First, the generated code is input into a Python interpreter to check whether it is valid. If the code is not valid, it cannot be run at all. If it is valid, the next question is whether it outputs the correct result for a given input pair.

In the candidate_gcd example, every line of the program runs without error. The FAIL lines are not crashes. They are correctness failures, and only the comparison step reveals them.

How the Harness Decides on One Test

The diagram below traces one test. The test case supplies an input pair and the expected value. The generated function receives the input and returns an actual value. The comparison step then decides between the two terminal results: PASS when the actual value matches the expected value, and FAIL when it does not. The same flow repeats for every test case in the set, which is why a single function can produce several FAIL lines in one report.

Test caseinput pair and expectedvalueGenerated functionreceives the input andreturns actual valueCompare actual withexpectedPASSactual matches expectedNext test in setFAILreport expected and actualinputactual valueequaldifferentrecordrecordrepeat
What happens step by step when the harness runs generated code on one test case, and where does the pass or fail decision branch?

Trace the diagram with the (15, 20) pair. The test case supplies the inputs 15 and 20 with expected value 5. The function returns 15. The comparison finds that 15 is different from 5, so the path leads to FAIL. The harness then moves to the next test in the set, and the loop continues until every case has been checked.

Anatomy of a Test Case

A test case is a scenario plus its expected output. The scenario is the situation the code is executed in: the inputs it receives. The expected output is what the code should return for that scenario. A unit test executes code in a scenario and compares the actual output to the expected output. Each scenario is one test, and the whole set of scenarios gives the measurement its coverage.

(12, 8)scenario: the inputs thefunction runs on4expected output: what thefunction should return
What are the parts of a single test case, and how does the scenario input map to the expected output it is checked against?

In the tuple (12, 8, 4) from the harness, the first two values form the scenario and the last value is the expected output. Reading the case this way makes the mapping explicit: the function is run on the scenario (12, 8), and its actual return value is checked against the expected output 4.

Unit Tests and Coverage

Code is typically validated with unit tests, in which the code is executed in different scenarios to ensure that it generates the expected outputs. Unit testing is a standard practice in software engineering. Each scenario is one test, and the whole set of scenarios is what gives a measurement of functional correctness its coverage.

Coverage therefore depends on the test set. A function checked on only one pair has been measured in one scenario. The four pairs in the harness are a small set, and the flawed candidate was caught by three of them. A larger and more varied set of scenarios gives a broader measurement, while a narrow set can let a wrong function pass.

Mistakes When Reading Test Results

  • Common mistake

    Judging code by how reasonable it looks

    What it looks like

    A function is clean and well named, so it is accepted without running any test.

    Why it fails

    The first question is whether the code does what it was supposed to do, and appearance does not answer that.

    Do this instead

    Run the code against test cases and compare its actual outputs with the expected outputs.

  • Common mistake

    Treating a program that runs without error as correct

    What it looks like

    candidate_gcd executes every line without an exception, yet three of its four pairs print FAIL.

    Why it fails

    Validity and correctness are separate stages. Code can be valid and still return the wrong answer.

    Do this instead

    Check the comparison result for each test case, not only whether the program finished.

  • Common mistake

    Treating one passing line as proof of correctness

    What it looks like

    The pair (8, 4) passes, so the candidate might seem correct.

    Why it fails

    The pass happens because min(8, 4) equals the correct answer in that one scenario. One scenario says nothing about the others.

    Do this instead

    Read the whole report and rely on the full set of test cases for coverage.

  • Common mistake

    Ignoring the FAIL lines because the program did not crash

Functional Correctness Versus Surface Comparison

It helps to contrast functional correctness with judging code by its text or structure. A surface-level judgment asks whether the code looks like an acceptable answer. A functional judgment asks whether running the code produces the right results. The table below sets the two side by side.

AspectSurface-level judgmentFunctional correctness
Guiding questionDoes the code look reasonable?Does it do what it was supposed to do?
What is examinedThe text or structure of the codeThe output produced when the code runs on test inputs
Basis for the decisionAppearance or resemblance to a referenceWhether actual output matches expected output
Typical evidenceA reading of the codeA test report with PASS and FAIL lines

Two ways to judge generated code

How Benchmarks Apply This Idea

A benchmark is a standardized dataset and metric used to evaluate AI models on a task. For code generation, a benchmark problem comes with a set of test cases, and the generated code is checked against them. The pipeline below shows the path a problem takes from prompt to final score.

Benchmark problemprompt with a set of testcasesModel generates codeTest executionrun code on each test caseFunctionalcorrectness scorepromptgenerated codepass or fail per test
How does a benchmark problem move from prompt to model-generated code to test execution to a final functional correctness score?

Trying the Harness Yourself

MEDIUM

Suppose you change candidate_gcd so that it returns max(a, b) instead of min(a, b), and keep the same four test tuples. Before running anything, predict which lines print PASS and which print FAIL. Then explain why the (8, 4) pair that passed before now behaves differently.

Hints
  • For each pair, compute max of the two inputs and compare that value with the expected value in the tuple.
  • For (8, 4), max returns 8, while the expected value is 4.
  • A PASS requires actual == expected, so check every line against that rule.

Key Takeaways

  • Functional correctness measures whether code performs its intended functionality, and it is treated as the ultimate metric for evaluating an application.
  • A measurement of functional correctness has two stages: first check that the code is valid, then check that its output matches the expected output for each input. Running without error does not establish correctness.
  • A test case is a scenario plus its expected output. A harness runs the generated code on each scenario, compares actual with expected, and reports PASS or FAIL.
  • Benchmarks such as HumanEval and MBPP for Python, and Spider, BIRD-SQL, and WikiSQL for text-to-SQL, use functional correctness and their test cases to decide whether generated output is accepted.

More concepts starting with E