Skip to content
behaviour-driven.org

Reference

BDD Tools by Language: BDD Framework Support and Project Status

A shallow wooden compartment tray holding blank brass tags, most compartments full, two empty, one holding tags in deep violet.

Which BDD tools are worth using follows almost entirely from the language a team already writes. This page lists the current BDD framework options by language, with the notation each one actually reads, its Gherkin support, its licence, and its project status as shown by the package registries rather than by reputation. Sorting BDD tools by language is the only ordering that matches how the question gets asked.

Registry and repository state checked 2026-08-31.

Gherkin support is the column that decides whether your examples can move to another tool later. A framework with full Gherkin support will parse a feature file written for any other Gherkin tool; the rest will not, and leaving one means rewriting the specifications rather than just the step definitions.

Every BDD framework, with Gherkin support and status

Implementation matrix

FrameworkLanguagesGherkinStatusLicence
BehatPHPFullactiveMIT
behavePythonFullmaintainedBSD-2-Clause
ConcordionJava, C#Own DSLlow-activityApache-2.0
Cucumber (Ruby)RubyFullactiveMIT
Cucumber JVMJava, Kotlin, Scala, GroovyFullactiveMIT
Cucumber.jsJavaScript, TypeScriptFullactiveMIT
Cypress Cucumber PreprocessorJavaScript, TypeScriptFullactiveMIT
GaugeJava, C#, Python, Ruby, JavaScriptOwn DSLactiveApache-2.0
GinkgoGoNoneactiveMIT
godogGoFullactiveMIT
JBehaveJavaFullmaintainedBSD-3-Clause
jest-cucumberJavaScript, TypeScriptFulllow-activityApache-2.0
KarateJava, JavaScriptOwn DSLactiveMIT
LettucePythonFullunmaintained → behaveGPL-3.0
pytest-bddPythonFulllow-activityMIT
radishPythonFullmaintainedMIT
ReqnrollC#, .NETFullactiveBSD-3-Clause
RSpecRubyNonemaintainedMIT
SpecFlowC#, .NETFullsuperseded → reqnrollBSD-3-Clause
SpockGroovy, JavaOwn DSLactiveApache-2.0

What each project status is based on

Status here is evidence, not opinion. Each line below is what was checked and when, so a reader can disagree with the conclusion and go and look.

Behatactive

GitHub Behat/Behat last push 2026-09-01, not archived

behavemaintained

PyPI behave 1.3.3 released 2025-09-04

Concordionlow-activity

GitHub concordion/concordion last push 2025-05-12, not archived

GitHub cucumber/cucumber-ruby last push 2026-08-31, not archived

GitHub cucumber/cucumber-jvm last push 2026-08-31, not archived

npm @cucumber/cucumber 13.2.1 released 2026-08-04

npm @badeball/cypress-cucumber-preprocessor 27.0.0 released 2026-08-27

Gaugeactive

GitHub getgauge/gauge last push 2026-08-21, not archived

Ginkgoactive

GitHub onsi/ginkgo last push 2026-08-10, not archived

godogactive

GitHub cucumber/godog last push 2026-08-31, not archived

JBehavemaintained

GitHub jbehave/jbehave-core last push 2026-03-05, not archived

jest-cucumberlow-activity

npm jest-cucumber 4.5.0 released 2024-07-25

Karateactive

GitHub karatelabs/karate last push 2026-09-01, not archived

Lettuceunmaintained

PyPI last release 0.2.23 uploaded 2016-07-26, no release in over nine years

pytest-bddlow-activity

PyPI pytest-bdd 8.1.0 released 2024-12-05

radishmaintained

PyPI radish-bdd 0.18.4 released 2026-02-24

Reqnrollactive

NuGet Reqnroll 3.3.4 released 2026-03-23

RSpecmaintained

RubyGems rspec 3.13.2 released 2025-10-21

SpecFlowsuperseded

Both GitHub repositories (SpecFlowOSS/SpecFlow and techtalk/SpecFlow) return 404 as of 2026-08-31; NuGet stops at 4.0.31-beta. Discontinued by Tricentis

Spockactive

GitHub spockframework/spock last push 2026-08-26, not archived

Chart: 14 of 20 BDD frameworks read Gherkin natively. By ecosystem, JVM has 6 frameworks of which 2 read Gherkin, JS/TS 5 of which 3, Python 5 of which 4, .NET 4 of which 2, Ruby 3 of which 1, Go 2 of which 1, and PHP 1 which does.
Counted from the framework list on this page. Frameworks appear in every ecosystem they support, so the ecosystem totals add up to more than twenty.

Use this chart on your own site

Choosing a BDD framework when the notation matters

One distinction is worth more than any feature comparison: whether the tool readsGherkin. A feature file written for one Gherkin tool can usually be read by another with only the step definitions rewritten, because the vocabulary the examples use is not tied to the runner, which means the examples survive a change of framework. Karate, Gauge and Concordion each use their own notation, and Spock, RSpec and Ginkgo have none, so moving away from them means rewriting the specifications themselves, and with them the conversation that produced them.

The second is maintenance. A BDD framework sits in the build of every developer on the team, so a project that has stopped releasing is a slow migration waiting to happen. SpecFlow is the current cautionary case: widely adopted across .NET, then discontinued, with its repositories removed. Teams on it have a migration to Reqnroll ahead of them, and the ones who checked project status regularly started earlier.

Everything else, including reporting, parallel execution and IDE integration, is genuinely a preference and changes too often to be worth freezing on a reference page.

Reading the status column honestly

Which signal decides the value depends on the project, and the difference matters. Where a framework ships as a package, the release date decides: somebody choosing a library needs to know whether a release shipped, and a commit between releases does not help them. Where there is no package, the repositorypush date decides. The evidence under each row names whichever applied, and both where both are known, so a project that is committed to daily while sitting twenty months without a release reads as exactly that.

The five values then mean specific things. Active is a release inside six months, or a push inside six weeks. Maintained means releases continue at a slower cadence, which for a mature framework with a stable notation is a reasonable state rather than a warning. Low activity means the gap has run to years rather than months, and is worth a second look before adopting.

Unmaintained is used only where the registries show no release for years, and superseded only where the project itself, or its author, has pointed elsewhere. Neither is inferred from a quiet quarter.

Two cautions on reading any list like this. A framework can be perfectly usable while formally unmaintained, if the notation it reads has not changed and the language it targets is stable. And a very active repository is not automatically the safer choice, since activity can equally mean the interface is still moving. What matters for a decision is whether someone will fix a break in the language runtime you depend on, which correlates with maintenance but is not the same question.

Frequently asked questions

Which BDD framework should a new project use?

The one that matches the language the team already writes, since the cost of a BDD framework is mostly in the step definitions and those live in your codebase. Across languages the safe defaults are Cucumber for Ruby, the JVM and JavaScript, Reqnroll for .NET, behave for Python, or pytest-bdd if the team is already on pytest, Behat for PHP and godog for Go.

What happened to SpecFlow?

It was discontinued. Both of its GitHub repositories now return 404 and its NuGet packages stop at a 4.0 beta. Reqnroll is the community fork, created by SpecFlow’s original author, and is the sensible target for both new projects and migrations.

Do all of these read Gherkin?

No, and the distinction matters if you want your examples to outlive the tool. Karate and Gauge use their own notation, Concordion uses HTML or Markdown, and Spock, RSpec and Ginkgo are spec-style frameworks with no Gherkin at all. Only the ones marked Gherkin will read a feature file written for another tool.

Is pytest-bdd better than behave?

It depends on existing investment rather than merit. pytest-bdd runs inside pytest, so a team already using pytest fixtures and plugins keeps all of it. behave is standalone and maps more directly onto Cucumber’s model, which helps if scenarios are shared with other languages.

How is project status decided on this page?

From the package registry and the source repository only, never from impression. Every row records what was checked, and the evidence is shown against each framework below. A framework is marked unmaintained only where the registries show no release for years.