Advertisement
Advertisement
CODE QUALITY

Cyclomatic Complexity Calculator — McCabe metric and test paths

Compute McCabe cyclomatic complexity three ways — from counted decision points, from a control flow graph, or approximately from pasted code — and see the independent paths a basis-path test set needs.

All three compute the same metric. The graph method is the definition; counting decisions is the shortcut that follows from it; pasted code is a rough keyword count.
A plain else adds nothing, because it is the path that already existed when the if was counted. An else-if is a new decision and does count.
Each && or || inside a condition creates its own branch, because the second operand may never be evaluated. Some tools omit these; say which convention you used when you report a number.
Used by the graph method only. Nodes are basic blocks, edges are the transfers of control between them.
Used by the pasted-code method only. It strips comments and quoted strings, then counts branch keywords and operators. It is a rough estimate, not a parser, and it does not understand your language's grammar.
A limit of ten per function is the figure discussed in the NIST publication linked below, with a higher ceiling allowed under a documented exception. Your own coding standard governs; this page applies whatever you enter.
Cyclomatic complexity
 
 
0
Linearly independent paths
0
Decision points counted
0
Average per function
0
Complexity per 100 lines
Against your limit
0%
Tip: cyclomatic complexity is a count of branching, not a measure of whether code is good. A long function with no decisions scores one, and a short one with a dense conditional scores far more.
Advertisement

The cyclomatic complexity calculator above computes the McCabe metric, which counts the number of linearly independent paths through a piece of code. It offers the three routes people actually use: the graph definition, the decision-point shortcut that follows from it, and an approximate keyword count over pasted source. It also reports the average per function and the density per hundred lines, which are usually more informative than a single total.

Arb Digital builds free tools that explain what a number does and does not mean. Cyclomatic complexity is a genuinely useful measure with a precise definition and a well-known failure mode: it is a count of branching, and branching is only one of several things that make code hard to work with. A page that returns a score and a verdict without saying that is selling a false sense of precision.

What Cyclomatic Complexity Actually Measures

Thomas McCabe defined the metric on a program's control flow graph, where each node is a straight-line block of code and each edge is a possible transfer of control. The complexity is the number of edges minus the number of nodes plus twice the number of connected components. For a single function with one entry and one exit, that reduces to the number of decision points plus one.

The number has a concrete meaning: it is the size of a basis set of paths through the code, meaning a set of independent paths from which every other path can be built as a combination. That is the property that makes it useful for testing, because it gives a lower bound on the number of test cases needed to exercise every branch at least once.

The definitive treatment is Structured Testing: A Testing Methodology Using the Cyclomatic Complexity Metric, by Arthur Watson, Thomas McCabe and Dolores Wallace, published as NIST Special Publication 500-235 in 1996. It sets out the basis-path testing method the metric was designed to support, which is the part most often forgotten when the number is used purely as a quality gauge.

How to Use It

  1. Pick a method. Decision counting is fastest for a function you are reading. The graph method is exact if you have already drawn the flow graph. Pasted code is a rough first pass.
  2. Count decisions carefully. Each if, else-if, loop, reachable case label, catch clause, short-circuit operator and ternary adds one. A plain else adds nothing.
  3. Say how many functions the count covers. For a whole module the complexity is the decision count plus the number of functions, and the average matters more than the total.
  4. Enter your own limit. The tool compares against whatever your coding standard says rather than imposing a threshold of its own.
  5. Read the density alongside the score. High complexity in a small function is a very different situation from the same score spread over a large one.

The Formula: How the Metric Is Calculated

The graph form is complexity equals edges minus nodes plus two times components. For a single connected function that is edges minus nodes plus two. The decision form is complexity equals decision points plus one for a single function, or decision points plus the number of functions for a module treated as a whole.

The two agree because every decision adds exactly one edge more than it adds nodes. An if statement splits one node into a condition node and two successors, adding one node and two edges on the branching side, and the net effect on edges minus nodes is one. That is why the shortcut works and why a plain else contributes nothing: it is the second successor that the if already paid for.

Work the defaults. The decision counts are four branches, two loops, three case labels, one catch, two short-circuit operators and one ternary, which is thirteen decision points. Spread across two functions the module complexity is thirteen plus two, which is fifteen, an average of 7.5 per function. Over 180 lines that is a density of 8.33 per hundred lines. Under the graph method preset, 21 edges minus 17 nodes plus two gives a complexity of six for a single function.

Advertisement

The Counting Conventions Tools Disagree About

If two tools give different answers for the same function, it is almost always a convention difference rather than a bug, and there are three common ones. The first is short-circuit operators. A condition written as one if with two ampersands has two extra branches, because the second operand may not be evaluated, and McCabe's original method counts them. Several popular linters do not, which makes their numbers systematically lower.

The second is the switch statement. Counting each reachable case label treats the construct as what it is, an n-way branch, and gives a complexity that rises with the number of cases. Some tools count the whole switch as one decision on the grounds that a flat dispatch table is easier to read than a chain of ifs, which is defensible as an opinion but is not the metric as defined.

The third is exception handling. Each catch or except clause is a path into which control can arrive, so it counts. Whether an implicit finally block or an unchecked exception path counts is a question different tools answer differently. None of this is a reason to distrust the metric; it is a reason to state which convention produced a number before comparing it with anyone else's.

What a High Score Does and Does Not Tell You

A high score tells you one specific thing: there are many independent paths, so there is a lot to test and a lot of state for a reader to hold in mind at once. That is a real cost and it is worth knowing. What it does not tell you is whether the code is well written, well named, correctly factored or appropriate for its problem.

A parser or a state machine with thirty cases may be perfectly clear, easy to extend and entirely correct while scoring far above any threshold, because the domain itself has thirty cases. Conversely, a function scoring three can be impenetrable if it mutates shared state, has a misleading name, or hides its real behaviour behind a chain of indirection. The metric is blind to all of that.

The most common misuse is refactoring purely to lower the number. Extracting three lines of a conditional into a helper called at exactly one place moves complexity rather than removing it, and often makes the code harder to follow, because the reader now has to jump. The honest use is as a flag: a function well above your limit deserves a look, and what you find there is a judgement, not an output.

Complexity and the Tests You Owe

The link back to testing is the part that gives the metric its teeth. A complexity of n means a basis set of n independent paths exists, so at least n test cases are needed to cover every branch. That is a floor and not a ceiling: covering every branch is weaker than covering every path, and the number of complete paths through a function with loops is unbounded.

Used that way, the score becomes a budget rather than a scold. A function scoring fifteen is telling you that fifteen tests are the minimum for branch coverage, and if you have four, you know the size of the gap. That framing tends to produce better conversations than a threshold alone, because it converts an abstract quality number into a specific piece of missing work.

How This Page Sits Beside the Other Developer Tools

The boundary in one sentence: this page measures branching in code, while the burndown chart calculator measures progress through a sprint. One looks at the artefact and the other at the schedule.

For other static measures, the CSS specificity calculator scores selectors by the cascade's own rules, the JavaScript minifier and the diff checker work on source directly, and the character counter gives raw size. The text readability checker applies a comparable idea to prose, scoring structure rather than meaning, and running into exactly the same limits.

Need a website that loads fast and actually works?

Arb Digital builds free tools like this one because useful pages earn attention. If you want tools, calculators or content built for your own audience, we can help.

See Our Web Design Work Talk to Arb Digital

Common Mistakes to Avoid

  • Counting a plain else — the else branch already exists as the if's second successor, so counting it double-counts the same decision.
  • Comparing numbers from different tools — short-circuit operators, switch statements and exception paths are all counted differently, so the convention has to match before the numbers do.
  • Extracting helpers just to lower the score — moving a branch into a function called from one place relocates complexity without reducing it, and usually costs readability.
  • Reading the metric as a quality verdict — it counts paths, not clarity, and a well-structured n-way dispatch scores badly while being perfectly readable.
  • Trusting a keyword count on real source — the pasted-code mode is an approximation that does not parse your language, and it will miscount in unusual syntax.

Related Free Tools From Arb Digital

Track the sprint that produced the code with the burndown chart calculator. For source-level work, use the diff checker, the JavaScript minifier and the CSS specificity calculator. Measure raw size with the character counter, score prose structure with the text readability checker, work out averages with the standard deviation calculator, and browse the full free online tools hub for everything else.

Frequently Asked Questions

What is cyclomatic complexity in one sentence?

It is the number of linearly independent paths through a piece of code, computed from its control flow graph as edges minus nodes plus twice the number of connected components, which for a single function equals the number of decision points plus one.

Does an else statement add to the count?

No. The if already created two successors, and the else is simply the second of them. An else-if is different: it introduces a new condition and therefore a new decision, so it does add one.

Why do two tools give me different numbers?

Almost always because of counting conventions. The main disagreements are whether short-circuit operators count as decisions, whether a switch counts once or once per case, and how exception paths are treated. State which convention you used before comparing figures.

What limit should I apply?

Whatever your coding standard sets. A limit of ten per function is the figure discussed in NIST Special Publication 500-235, with a higher ceiling allowed under a documented exception, but the appropriate number depends on the domain and on the team. This page uses the limit you enter.

Does a high score mean the code is bad?

No. It means there are many paths, so there is more to test and more to hold in mind. Some problems genuinely have many cases, and a clear n-way dispatch can score high while being easy to read. The score is a flag for a look, not a verdict.

How does it relate to test coverage?

The complexity is the minimum number of test cases needed to exercise every branch at least once, since it is the size of a basis set of paths. It is a floor rather than a target, because branch coverage is weaker than path coverage.

How accurate is the pasted-code mode?

It is an approximation. It removes comments and quoted strings, then counts branch keywords and short-circuit operators. It does not parse the language, so unusual syntax, keywords used as identifiers and languages it was not designed for will produce a wrong count.

Should I refactor to reduce the number?

Only if the refactoring genuinely helps a reader. Extracting a branch into a helper called from exactly one place lowers the score of one function while raising the total work of understanding the module, which is not an improvement.

Advertisement
Advertisement

Take it further