Repository: go-bdd/gobdd (go)

Issue:
Merge context package with the main package
**Is your feature request related to a problem? Please describe.**
Currently the stdlib context and gobdd context packages can only be used in one file together with import aliases.

**Describe the solution you'd like**
Merge the context package with the main package. The functionality belongs closely together anyway.

**Describe alternatives you've considered**
Create an interface in the main package (interfaces belong to consumers).

Related #83

**Additional context**
This could be a backwards compatible change: we could keep the original package and add a type alias pointing to the new type in the root package.


Pull request:
Merge context package into the main package
Fixes #96

This is a fully backwards compatible change by adding aliases for the necessary type (Context).

## ToDos

- [ ] `NewContext` does not have to be exported. Should it be?

## Possible alternatives

- Introduce an interface: that would be a somewhat backward incompatible change, but the Context should only be used by consumers as a type, it shouldn't be manually instantiated. (An interface can still be added after this PR)
- Add a type alias to the context package: would be less code change, but eventually the context package should go away

Patch:
diff --git a/README.md b/README.md
index 71551be..6d62235 100644
--- a/README.md
+++ b/README.md
@@ -34,13 +34,13 @@ Feature: math operations
 Add a new test `main_test.go`:
 
 ```go
-func add(t gobdd.StepTest, ctx context.Context, var1, var2 int) context.Context{
+func add(t gobdd.StepTest, ctx gobdd.Context, var1, var2 int) {
 	res := var1 + var2
 	ctx.Set("sumRes", res)
 	return ctx
 }
 
-func check(t gobdd.StepTest, ctx context.Context, sum int) context.Context{
+func check(t gobdd.StepTest, ctx gobdd.Context, sum int) {
 	received, err := ctx.GetInt("sumRes")
 	if err != nil {
 		t.Error(err)
diff --git a/context.go b/context.go
new file mode 100644
index 0000000..311ab78
--- /dev/null
+++ b/context.go
@@ -0,0 +1,72 @@
+package gobdd
+
+import (
+	"fmt"
+)
+
+// Holds data from previously executed steps
+type Context struct {
+	values map[interface{}]interface{}
+}
+
+// Creates a new (empty) context struct
+func NewContext() Context {
+	return Context{
+		values: map[interface{}]interface{}{},
+	}
+}
+
+// Clone creates a copy of the context
+func (ctx Context) Clone() Context {
+	c := Context{
+		values: map[interface{}]interface{}{},
+	}
+
+	for k, v := range ctx.values {
+		c.Set(k, v)
+	}
+
+	return c
+}
+
+// Sets the value under the key
+func (ctx Context) Set(key interface{}, value interface{}) {
+	ctx.values[key] = value
+}
+
+// Returns the data under the key.
+// If couldn't find anything but the default value is provided, returns the default value.
+// Otherwise, it returns an error.
+func (ctx Context) Get(key interface{}, defaultValue ...interface{}) (interface{}, error) {
+	if _, ok := ctx.values[key]; !ok {
+		if len(defaultValue) == 1 {
+			return defaultValue[0], nil
+		}
+
+		return nil, fmt.Errorf("the key %+v does not exist", key)
+	}
+
+	return ctx.values[key], nil
+}
+
+// It is a shortcut for getting the value already casted as error.
+func (ctx Context) GetError(key interface{}, defaultValue ...error) (error, error) {
+	if _, ok := ctx.values[key]; !ok {
+		if len(defaultValue) == 1 {
+			return defaultValue[0], nil
+		}
+
+		return nil, fmt.Errorf("the key %+v does not exist", key)
+	}
+
+	if ctx.values[key] == nil {
+		return nil, nil
+	}
+
+	value, ok := ctx.values[key].(error)
+	if !ok {
+		return nil, fmt.Errorf("the expected value is not error  (%T)", key)
+	}
+
+	return value, nil
+}
diff --git a/context/context.go b/context/context.go
index 62fa9f3..06369d3 100644
--- a/context/context.go
+++ b/context/context.go
@@ -1,72 +1,15 @@
 package context
 
 import (
-	"fmt"
+	"github.com/go-bdd/gobdd"
 )
 
 // Holds data from previously executed steps
-type Context struct {
-	values map[interface{}]interface{}
-}
+// Deprecated: use gobdd.Context instead.
+type Context = gobdd.Context
 
 // Creates a new (empty) context struct
+// Deprecated: use gobdd.NewContext instead.
 func New() Context {
-	return Context{
-		values: map[interface{}]interface{}{},
-	}
-}
-
-// Clone creates a copy of the context
-func (ctx Context) Clone() Context {
-	c := Context{
-		values: map[interface{}]interface{}{},
-	}
-
-	for k, v := range ctx.values {
-		c.Set(k, v)
-	}
-
-	return c
-}
-
-// Sets the value under the key
-func (ctx Context) Set(key interface{}, value interface{}) {
-	ctx.values[key] = value
-}
-
-// Returns the data under the key.
-// If couldn't find anything but the default value is provided, returns the default value.
-// Otherwise, it returns an error.
-func (ctx Context) Get(key interface{}, defaultValue ...interface{}) (interface{}, error) {
-	if _, ok := ctx.values[key]; !ok {
-		if len(defaultValue) == 1 {
-			return defaultValue[0], nil
-		}
-
-		return nil, fmt.Errorf("the key %+v does not exist", key)
-	}
-
-	return ctx.values[key], nil
-}
-
-// It is a shortcut for getting the value already casted as error.
-func (ctx Context) GetError(key interface{}, defaultValue ...error) (error, error) {
-	if _, ok := ctx.values[key]; !ok {
-		if len(defaultValue) == 1 {
-			return defaultValue[0], nil
-		}
-
-		return nil, fmt.Errorf("the key %+v does not exist", key)
-	}
-
-	if ctx.values[key] == nil {
-		return nil, nil
-	}
-
-	value, ok := ctx.values[key].(error)
-	if !ok {
-		return nil, fmt.Errorf("the expected value is not error  (%T)", key)
-	}
-
-	return value, nil
+	return gobdd.NewContext()
 }
diff --git a/context/doc.go b/context/doc.go
deleted file mode 100644
index e20de23..0000000
--- a/context/doc.go
+++ /dev/null
@@ -1,12 +0,0 @@
-// The context is created to hold all the required data from previous steps to be reused.
-// Its goal preventing from holding a global state if it's not needed what improves maintainability.
-// The context has a set of helper functions which simplify the end-user code.
-//  ctx.Set(name{}, "John")
-//  fmt.Printf("Hi %s\n", ctx.GetString(name{})) // prints "Hi John"
-//
-// Good practices
-//
-// It’s a good practice to use custom structs as keys instead of strings or any built-in types
-// to avoid collisions between steps using context.
-
-package context
diff --git a/context/get.go b/context_get.go
similarity index 99%
rename from context/get.go
rename to context_get.go
index e5fc294..eade772 100644
--- a/context/get.go
+++ b/context_get.go
@@ -1,5 +1,5 @@
 // Code generated .* DO NOT EDIT.	
-package context
+package gobdd
 
 import "fmt"
 
diff --git a/docs/creating-steps.markdown b/docs/creating-steps.markdown
index 193c9fb..0951dd6 100644
--- a/docs/creating-steps.markdown
+++ b/docs/creating-steps.markdown
@@ -8,7 +8,7 @@ title: Creating steps
 Every step function should accept the `StepTest` as the first 2 parameters and returns the `Context`. Here's an example:
 
 ```go
-type StepFunc func(gobdd.StepTest, ctx context.Context, var1 int, var2 string)
+type StepFunc func(gobdd.StepTest, ctx gobdd.Context, var1 int, var2 string)
 ```
 
 What's important to stress - the context is a [custom struct](https://github.com/go-bdd/gobdd/tree/master/context), not the built-in interface.
diff --git a/docs/quick-start.markdown b/docs/quick-start.markdown
index bb932c2..eb487f6 100644
--- a/docs/quick-start.markdown
+++ b/docs/quick-start.markdown
@@ -12,12 +12,12 @@ go get github.com/go-bdd/gobdd
 Add a new test `main_test.go`:
 
 ```go
-func add(t gobdd.StepTest, ctx context.Context, var1, var2 int) {
+func add(t gobdd.StepTest, ctx gobdd.Context, var1, var2 int) {
 	res := var1 + var2
 	ctx.Set("sumRes", res)
 }
 
-func check(t gobdd.StepTest, ctx context.Context, sum int) {
+func check(t gobdd.StepTest, ctx gobdd.Context, sum int) {
 	received, err := ctx.GetInt("sumRes")
     if err != nil {
         t.Error(err)
diff --git a/gen/ctxgen.go b/gen/ctxgen.go
index 46ce6c4..ce5fcd6 100644
--- a/gen/ctxgen.go
+++ b/gen/ctxgen.go
@@ -71,7 +71,7 @@ func main() {
 		},
 	}
 
-	f, err := os.Create("context/get.go")
+	f, err := os.Create("context_get.go")
 	die(err)
 
 	var tmpl = template.Must(template.New("").Funcs(funcMap).Parse(getTmpl))
@@ -82,7 +82,7 @@ func main() {
 	die(err)
 	f.Close()
 
-	f, err = os.Create("context/get_test.go")
+	f, err = os.Create("context_get_test.go")
 	die(err)
 
 	tmpl = template.Must(template.New("").Funcs(funcMap).Parse(testTmpl))
@@ -101,13 +101,13 @@ func die(err error) {
 }
 
 const testTmpl = `// Code generated .* DO NOT EDIT.	
-package context
+package gobdd
 
 import "testing"
 import "errors"
 
 func TestContext_GetError(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := errors.New("new err")
 	ctx.Set("test", expected)
 	received, err := ctx.GetError("test")
@@ -121,7 +121,7 @@ func TestContext_GetError(t *testing.T) {
 
 {{ range .Types }}
 func TestContext_Get{{ .Name | Title }}(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := {{ .Name }}({{ .Value | noescape }})
 	ctx.Set("test", expected)
 	received, err := ctx.Get{{ .Name | Title }}("test")
@@ -134,7 +134,7 @@ func TestContext_Get{{ .Name | Title }}(t *testing.T) {
 }
 
 func TestContext_Get{{ .Name | Title }}_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := {{ .Name }}({{ .Value | noescape }})
 	received, err := ctx.Get{{ .Name | Title }}("test", defaultValue)
 	if err != nil {
@@ -146,7 +146,7 @@ func TestContext_Get{{ .Name | Title }}_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_Get{{ .Name | Title }}_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.Get{{ .Name | Title }}("test", {{ .Value | noescape }}, {{ .Value | noescape }})
 	if err == nil  {
 		t.Error("the Get{{ .Name | Title }} should return an error")
@@ -154,7 +154,7 @@ func TestContext_Get{{ .Name | Title }}_ShouldReturnErrorWhenMoreThanOneDefaultV
 }
 
 func TestContext_Get{{ .Name | Title }}_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.Get{{ .Name | Title }}("test")
 	if err == nil  {
 		t.Error("the Get{{ .Name | Title }} should return an error")
@@ -164,7 +164,7 @@ func TestContext_Get{{ .Name | Title }}_ErrorOnNotFound(t *testing.T) {
 `
 
 const getTmpl = `// Code generated .* DO NOT EDIT.	
-package context
+package gobdd
 
 import "fmt"
 
diff --git a/gobdd.go b/gobdd.go
index d7fbc7d..e97b429 100644
--- a/gobdd.go
+++ b/gobdd.go
@@ -16,7 +16,6 @@ import (
 
 	"github.com/cucumber/gherkin-go/v13"
 	msgs "github.com/cucumber/messages-go/v12"
-	"github.com/go-bdd/gobdd/context"
 )
 
 // Holds all the information about the suite (options, steps to execute etc)
@@ -32,8 +31,8 @@ type SuiteOptions struct {
 	featuresPaths  string
 	ignoreTags     []string
 	tags           []string
-	beforeScenario []func(ctx context.Context)
-	afterScenario  []func(ctx context.Context)
+	beforeScenario []func(ctx Context)
+	afterScenario  []func(ctx Context)
 	runInParallel  bool
 }
 
@@ -43,8 +42,8 @@ func NewSuiteOptions() SuiteOptions {
 		featuresPaths:  "features/*.feature",
 		ignoreTags:     []string{},
 		tags:           []string{},
-		beforeScenario: []func(ctx context.Context){},
-		afterScenario:  []func(ctx context.Context){},
+		beforeScenario: []func(ctx Context){},
+		afterScenario:  []func(ctx Context){},
 	}
 }
 
@@ -72,14 +71,14 @@ func WithTags(tags []string) func(*SuiteOptions) {
 }
 
 // WithBeforeScenario configures functions that should be executed before every scenario
-func WithBeforeScenario(f func(ctx context.Context)) func(*SuiteOptions) {
+func WithBeforeScenario(f func(ctx Context)) func(*SuiteOptions) {
 	return func(options *SuiteOptions) {
 		options.beforeScenario = append(options.beforeScenario, f)
 	}
 }
 
 // WithAfterScenario configures functions that should be executed after every scenario
-func WithAfterScenario(f func(ctx context.Context)) func(*SuiteOptions) {
+func WithAfterScenario(f func(ctx Context)) func(*SuiteOptions) {
 	return func(options *SuiteOptions) {
 		options.afterScenario = append(options.afterScenario, f)
 	}
@@ -135,9 +134,9 @@ func NewSuite(t TestingT, optionClosures ...func(*SuiteOptions)) *Suite {
 // when a step definition matches the provided regular expression.
 //
 // A step function can have any number of parameters (even zero),
-// but it MUST accept a gobdd.StepTest and context.Context as the first parameters (if there is any):
+// but it MUST accept a gobdd.StepTest and gobdd.Context as the first parameters (if there is any):
 //
-// 	func myStepFunction(t gobdd.StepTest, ctx context.Context, first int, second int) {
+// 	func myStepFunction(t gobdd.StepTest, ctx gobdd.Context, first int, second int) {
 // 	}
 func (s *Suite) AddStep(expr string, step interface{}) {
 	err := validateStepFunc(step)
@@ -168,9 +167,9 @@ func (s *Suite) AddStep(expr string, step interface{}) {
 // when a step definition matches the provided regular expression.
 //
 // A step function can have any number of parameters (even zero),
-// but it MUST accept a gobdd.StepTest and context.Context as the first parameters (if there is any):
+// but it MUST accept a gobdd.StepTest and gobdd.Context as the first parameters (if there is any):
 //
-// 	func myStepFunction(t gobdd.StepTest, ctx context.Context, first int, second int) {
+// 	func myStepFunction(t gobdd.StepTest, ctx gobdd.Context, first int, second int) {
 // 	}
 func (s *Suite) AddRegexStep(expr *regexp.Regexp, step interface{}) {
 	err := validateStepFunc(step)
@@ -257,7 +256,7 @@ func (s *Suite) runFeature(feature *msgs.GherkinDocument_Feature) error {
 				t.Log(fmt.Sprintf("Skipping scenario %s", scenario.Name))
 				continue
 			}
-			ctx := context.New()
+			ctx := NewContext()
 			s.runScenario(ctx, scenario, bkgSteps, t)
 		}
 	})
@@ -353,19 +352,19 @@ func (s *Suite) stepFromExample(
 	return stepName, expr
 }
 
-func (s *Suite) callBeforeScenarios(ctx context.Context) {
+func (s *Suite) callBeforeScenarios(ctx Context) {
 	for _, f := range s.options.beforeScenario {
 		f(ctx)
 	}
 }
 
-func (s *Suite) callAfterScenarios(ctx context.Context) {
+func (s *Suite) callAfterScenarios(ctx Context) {
 	for _, f := range s.options.afterScenario {
 		f(ctx)
 	}
 }
 
-func (s *Suite) runScenario(ctx context.Context, scenario *msgs.GherkinDocument_Feature_Scenario,
+func (s *Suite) runScenario(ctx Context, scenario *msgs.GherkinDocument_Feature_Scenario,
 	bkg *msgs.GherkinDocument_Feature_Background, t *testing.T) {
 	s.callBeforeScenarios(ctx)
 
@@ -387,13 +386,13 @@ func (s *Suite) runScenario(ctx context.Context, scenario *msgs.GherkinDocument_
 	})
 }
 
-func (s *Suite) runSteps(ctx context.Context, t *testing.T, steps []*msgs.GherkinDocument_Feature_Step) {
+func (s *Suite) runSteps(ctx Context, t *testing.T, steps []*msgs.GherkinDocument_Feature_Step) {
 	for _, step := range steps {
 		s.runStep(ctx, t, step)
 	}
 }
 
-func (s *Suite) runStep(ctx context.Context, t *testing.T, step *msgs.GherkinDocument_Feature_Step) {
+func (s *Suite) runStep(ctx Context, t *testing.T, step *msgs.GherkinDocument_Feature_Step) {
 	defer func() {
 		if r := recover(); r != nil {
 			t.Error(r)
@@ -413,7 +412,7 @@ func (s *Suite) runStep(ctx context.Context, t *testing.T, step *msgs.GherkinDoc
 	})
 }
 
-func (def *stepDef) run(ctx context.Context, t TestingT, params [][]byte) {
+func (def *stepDef) run(ctx Context, t TestingT, params [][]byte) { // nolint:interfacer
 	defer func() {
 		if r := recover(); r != nil {
 			t.Errorf("%+v", r)
diff --git a/steps.go b/steps.go
index 044fae2..9ed3fad 100644
--- a/steps.go
+++ b/steps.go
@@ -3,8 +3,6 @@ package gobdd
 import (
 	"errors"
 	"reflect"
-
-	"github.com/go-bdd/gobdd/context"
 )
 
 func validateStepFunc(f interface{}) error {
@@ -26,7 +24,7 @@ func validateStepFunc(f interface{}) error {
 
 	val = value.Type().In(1)
 
-	n := val.ConvertibleTo(reflect.TypeOf((*context.Context)(nil)).Elem())
+	n := val.ConvertibleTo(reflect.TypeOf((*Context)(nil)).Elem())
 	if !n {
 		return errors.New("the function should have Context as the second argument")
 	}


Test patch:
diff --git a/context/get_test.go b/context_get_test.go
similarity index 91%
rename from context/get_test.go
rename to context_get_test.go
index 2136494..da1ea3f 100644
--- a/context/get_test.go
+++ b/context_get_test.go
@@ -1,11 +1,11 @@
 // Code generated .* DO NOT EDIT.	
-package context
+package gobdd
 
 import "testing"
 import "errors"
 
 func TestContext_GetError(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := errors.New("new err")
 	ctx.Set("test", expected)
 	received, err := ctx.GetError("test")
@@ -19,7 +19,7 @@ func TestContext_GetError(t *testing.T) {
 
 
 func TestContext_GetString(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := string("example text")
 	ctx.Set("test", expected)
 	received, err := ctx.GetString("test")
@@ -32,7 +32,7 @@ func TestContext_GetString(t *testing.T) {
 }
 
 func TestContext_GetString_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := string("example text")
 	received, err := ctx.GetString("test", defaultValue)
 	if err != nil {
@@ -44,7 +44,7 @@ func TestContext_GetString_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetString_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetString("test", "example text", "example text")
 	if err == nil  {
 		t.Error("the GetString should return an error")
@@ -52,7 +52,7 @@ func TestContext_GetString_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testi
 }
 
 func TestContext_GetString_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetString("test")
 	if err == nil  {
 		t.Error("the GetString should return an error")
@@ -60,7 +60,7 @@ func TestContext_GetString_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetInt(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := int(123)
 	ctx.Set("test", expected)
 	received, err := ctx.GetInt("test")
@@ -73,7 +73,7 @@ func TestContext_GetInt(t *testing.T) {
 }
 
 func TestContext_GetInt_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := int(123)
 	received, err := ctx.GetInt("test", defaultValue)
 	if err != nil {
@@ -85,7 +85,7 @@ func TestContext_GetInt_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetInt_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt("test", 123, 123)
 	if err == nil  {
 		t.Error("the GetInt should return an error")
@@ -93,7 +93,7 @@ func TestContext_GetInt_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.
 }
 
 func TestContext_GetInt_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt("test")
 	if err == nil  {
 		t.Error("the GetInt should return an error")
@@ -101,7 +101,7 @@ func TestContext_GetInt_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetInt8(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := int8(123)
 	ctx.Set("test", expected)
 	received, err := ctx.GetInt8("test")
@@ -114,7 +114,7 @@ func TestContext_GetInt8(t *testing.T) {
 }
 
 func TestContext_GetInt8_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := int8(123)
 	received, err := ctx.GetInt8("test", defaultValue)
 	if err != nil {
@@ -126,7 +126,7 @@ func TestContext_GetInt8_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetInt8_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt8("test", 123, 123)
 	if err == nil  {
 		t.Error("the GetInt8 should return an error")
@@ -134,7 +134,7 @@ func TestContext_GetInt8_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing
 }
 
 func TestContext_GetInt8_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt8("test")
 	if err == nil  {
 		t.Error("the GetInt8 should return an error")
@@ -142,7 +142,7 @@ func TestContext_GetInt8_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetInt16(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := int16(123)
 	ctx.Set("test", expected)
 	received, err := ctx.GetInt16("test")
@@ -155,7 +155,7 @@ func TestContext_GetInt16(t *testing.T) {
 }
 
 func TestContext_GetInt16_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := int16(123)
 	received, err := ctx.GetInt16("test", defaultValue)
 	if err != nil {
@@ -167,7 +167,7 @@ func TestContext_GetInt16_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetInt16_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt16("test", 123, 123)
 	if err == nil  {
 		t.Error("the GetInt16 should return an error")
@@ -175,7 +175,7 @@ func TestContext_GetInt16_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testin
 }
 
 func TestContext_GetInt16_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt16("test")
 	if err == nil  {
 		t.Error("the GetInt16 should return an error")
@@ -183,7 +183,7 @@ func TestContext_GetInt16_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetInt32(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := int32(123)
 	ctx.Set("test", expected)
 	received, err := ctx.GetInt32("test")
@@ -196,7 +196,7 @@ func TestContext_GetInt32(t *testing.T) {
 }
 
 func TestContext_GetInt32_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := int32(123)
 	received, err := ctx.GetInt32("test", defaultValue)
 	if err != nil {
@@ -208,7 +208,7 @@ func TestContext_GetInt32_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetInt32_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt32("test", 123, 123)
 	if err == nil  {
 		t.Error("the GetInt32 should return an error")
@@ -216,7 +216,7 @@ func TestContext_GetInt32_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testin
 }
 
 func TestContext_GetInt32_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt32("test")
 	if err == nil  {
 		t.Error("the GetInt32 should return an error")
@@ -224,7 +224,7 @@ func TestContext_GetInt32_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetInt64(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := int64(123)
 	ctx.Set("test", expected)
 	received, err := ctx.GetInt64("test")
@@ -237,7 +237,7 @@ func TestContext_GetInt64(t *testing.T) {
 }
 
 func TestContext_GetInt64_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := int64(123)
 	received, err := ctx.GetInt64("test", defaultValue)
 	if err != nil {
@@ -249,7 +249,7 @@ func TestContext_GetInt64_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetInt64_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt64("test", 123, 123)
 	if err == nil  {
 		t.Error("the GetInt64 should return an error")
@@ -257,7 +257,7 @@ func TestContext_GetInt64_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testin
 }
 
 func TestContext_GetInt64_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetInt64("test")
 	if err == nil  {
 		t.Error("the GetInt64 should return an error")
@@ -265,7 +265,7 @@ func TestContext_GetInt64_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetFloat32(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := float32(123.5)
 	ctx.Set("test", expected)
 	received, err := ctx.GetFloat32("test")
@@ -278,7 +278,7 @@ func TestContext_GetFloat32(t *testing.T) {
 }
 
 func TestContext_GetFloat32_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := float32(123.5)
 	received, err := ctx.GetFloat32("test", defaultValue)
 	if err != nil {
@@ -290,7 +290,7 @@ func TestContext_GetFloat32_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetFloat32_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetFloat32("test", 123.5, 123.5)
 	if err == nil  {
 		t.Error("the GetFloat32 should return an error")
@@ -298,7 +298,7 @@ func TestContext_GetFloat32_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *test
 }
 
 func TestContext_GetFloat32_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetFloat32("test")
 	if err == nil  {
 		t.Error("the GetFloat32 should return an error")
@@ -306,7 +306,7 @@ func TestContext_GetFloat32_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetFloat64(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := float64(123.5)
 	ctx.Set("test", expected)
 	received, err := ctx.GetFloat64("test")
@@ -319,7 +319,7 @@ func TestContext_GetFloat64(t *testing.T) {
 }
 
 func TestContext_GetFloat64_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := float64(123.5)
 	received, err := ctx.GetFloat64("test", defaultValue)
 	if err != nil {
@@ -331,7 +331,7 @@ func TestContext_GetFloat64_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetFloat64_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetFloat64("test", 123.5, 123.5)
 	if err == nil  {
 		t.Error("the GetFloat64 should return an error")
@@ -339,7 +339,7 @@ func TestContext_GetFloat64_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *test
 }
 
 func TestContext_GetFloat64_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetFloat64("test")
 	if err == nil  {
 		t.Error("the GetFloat64 should return an error")
@@ -347,7 +347,7 @@ func TestContext_GetFloat64_ErrorOnNotFound(t *testing.T) {
 }
 
 func TestContext_GetBool(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	expected := bool(false)
 	ctx.Set("test", expected)
 	received, err := ctx.GetBool("test")
@@ -360,7 +360,7 @@ func TestContext_GetBool(t *testing.T) {
 }
 
 func TestContext_GetBool_WithDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	defaultValue := bool(false)
 	received, err := ctx.GetBool("test", defaultValue)
 	if err != nil {
@@ -372,7 +372,7 @@ func TestContext_GetBool_WithDefaultValue(t *testing.T) {
 }
 
 func TestContext_GetBool_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetBool("test", false, false)
 	if err == nil  {
 		t.Error("the GetBool should return an error")
@@ -380,7 +380,7 @@ func TestContext_GetBool_ShouldReturnErrorWhenMoreThanOneDefaultValue(t *testing
 }
 
 func TestContext_GetBool_ErrorOnNotFound(t *testing.T) {
-	ctx := New()
+	ctx := NewContext()
 	_, err := ctx.GetBool("test")
 	if err == nil  {
 		t.Error("the GetBool should return an error")
diff --git a/context/context_test.go b/context_test.go
similarity index 66%
rename from context/context_test.go
rename to context_test.go
index a166ca4..e58065d 100644
--- a/context/context_test.go
+++ b/context_test.go
@@ -1,4 +1,4 @@
-package context
+package gobdd
 
 import (
 	"testing"
@@ -6,8 +6,8 @@ import (
 	"github.com/stretchr/testify/assert"
 )
 
-func TestNilInGetError(t *testing.T) {
-	ctx := New()
+func TestContextNilInGetError(t *testing.T) {
+	ctx := NewContext()
 	ctx.Set("err", nil)
 
 	res, err := ctx.GetError("err")
diff --git a/gobdd_test.go b/gobdd_test.go
index 53ef03a..b40a0e0 100644
--- a/gobdd_test.go
+++ b/gobdd_test.go
@@ -8,7 +8,6 @@ import (
 
 	msgs "github.com/cucumber/messages-go/v12"
 	"github.com/go-bdd/assert"
-	"github.com/go-bdd/gobdd/context"
 )
 
 func TestScenarios(t *testing.T) {
@@ -49,7 +48,7 @@ func TestScenarioOutlineExecutesAllTests(t *testing.T) {
 	c := 0
 	suite := NewSuite(t, WithFeaturesPath("features/outline.feature"))
 	suite.AddStep(`I add (\d+) and (\d+)`, add)
-	suite.AddStep(`the result should equal (\d+)`, func(t StepTest, ctx context.Context, sum int) {
+	suite.AddStep(`the result should equal (\d+)`, func(t StepTest, ctx Context, sum int) {
 		c++
 		check(t, ctx, sum)
 	})
@@ -101,7 +100,7 @@ func TestTags(t *testing.T) {
 
 func TestWithAfterScenario(t *testing.T) {
 	c := false
-	suite := NewSuite(t, WithFeaturesPath("features/empty.feature"), WithAfterScenario(func(ctx context.Context) {
+	suite := NewSuite(t, WithFeaturesPath("features/empty.feature"), WithAfterScenario(func(ctx Context) {
 		c = true
 	}))
 	suite.Run()
@@ -113,7 +112,7 @@ func TestWithAfterScenario(t *testing.T) {
 
 func TestWithBeforeScenario(t *testing.T) {
 	c := false
-	suite := NewSuite(t, WithFeaturesPath("features/empty.feature"), WithBeforeScenario(func(ctx context.Context) {
+	suite := NewSuite(t, WithFeaturesPath("features/empty.feature"), WithBeforeScenario(func(ctx Context) {
 		c = true
 	}))
 	suite.Run()
@@ -134,8 +133,8 @@ func TestInvalidFunctionSignature(t *testing.T) {
 		f interface{}
 	}{
 		"nil":                              {},
-		"func without return value":        {f: func(ctx context.Context) {}},
-		"func with invalid return value":   {f: func(ctx context.Context) int { return 0 }},
+		"func without return value":        {f: func(ctx Context) {}},
+		"func with invalid return value":   {f: func(ctx Context) int { return 0 }},
 		"func without arguments":           {f: func() error { return errors.New("") }},
 		"func with invalid first argument": {f: func(i int) error { return errors.New("") }},
 	}
@@ -170,7 +169,7 @@ func TestFailureOutput(t *testing.T) {
 			def := stepDef{f: testCase.f}
 
 			tester := &mockTester{}
-			def.run(context.New(), tester, nil)
+			def.run(NewContext(), tester, nil)
 			err := assert.Equals(testCase.expectedErrors, tester.errors)
 			if err != nil {
 				t.Fatal(err)
@@ -179,17 +178,17 @@ func TestFailureOutput(t *testing.T) {
 	}
 }
 
-func addf(_ StepTest, ctx context.Context, var1, var2 float32) {
+func addf(_ StepTest, ctx Context, var1, var2 float32) {
 	res := var1 + var2
 	ctx.Set("sumRes", res)
 }
 
-func add(_ StepTest, ctx context.Context, var1, var2 int) {
+func add(_ StepTest, ctx Context, var1, var2 int) {
 	res := var1 + var2
 	ctx.Set("sumRes", res)
 }
 
-func checkf(t StepTest, ctx context.Context, sum float32) {
+func checkf(t StepTest, ctx Context, sum float32) {
 	received, err := ctx.Get("sumRes")
 	if err != nil {
 		t.Error(err.Error())
@@ -202,7 +201,7 @@ func checkf(t StepTest, ctx context.Context, sum float32) {
 	}
 }
 
-func check(t StepTest, ctx context.Context, sum int) {
+func check(t StepTest, ctx Context, sum int) {
 	received, err := ctx.Get("sumRes")
 	if err != nil {
 		t.Error(err)
@@ -214,19 +213,19 @@ func check(t StepTest, ctx context.Context, sum int) {
 	}
 }
 
-func fail(t StepTest, _ context.Context) {
+func fail(t StepTest, _ Context) {
 	t.Error("the step should never be executed")
 }
 
-func failure(t StepTest, _ context.Context) {
+func failure(t StepTest, _ Context) {
 	t.Error("the step failed")
 }
 
-func panics(_ StepTest, _ context.Context) {
+func panics(_ StepTest, _ Context) {
 	panic(errors.New("the step panicked"))
 }
 
-func pass(_ StepTest, _ context.Context) {}
+func pass(_ StepTest, _ Context) {}
 
 type mockTester struct {
 	fatalCalled int
diff --git a/steps_context_test.go b/steps_context_test.go
new file mode 100644
index 0000000..8bf175d
--- /dev/null
+++ b/steps_context_test.go
@@ -0,0 +1,35 @@
+package gobdd_test
+
+import (
+	"testing"
+
+	"github.com/go-bdd/gobdd"
+	"github.com/go-bdd/gobdd/context"
+)
+
+func TestValidateStepFunc_Context(t *testing.T) {
+	testCases := map[string]interface{}{
+		"function with invalid first argument": func(int, context.Context) {},
+	}
+
+	for name, testCase := range testCases {
+		t.Run(name, func(t *testing.T) {
+			if err := gobdd.ValidateStepFunc(testCase); err == nil {
+				t.Errorf("the test should fail for the function")
+			}
+		})
+	}
+}
+
+func TestValidateStepFunc_ValidFunction_Context(t *testing.T) {
+	if err := gobdd.ValidateStepFunc(func(gobdd.StepTest, context.Context) {}); err != nil {
+		t.Errorf("the test should NOT fail for the function: %s", err)
+	}
+}
+
+func TestValidateStepFunc_ReturnContext_Context(t *testing.T) {
+	err := gobdd.ValidateStepFunc(func(gobdd.StepTest, context.Context) context.Context { return context.Context{} })
+	if err != nil {
+		t.Errorf("step function returning a context should NOT fail validation: %s", err)
+	}
+}
diff --git a/steps_test.go b/steps_test.go
index 809ec5e..cf65269 100644
--- a/steps_test.go
+++ b/steps_test.go
@@ -2,15 +2,13 @@ package gobdd
 
 import (
 	"testing"
-
-	"github.com/go-bdd/gobdd/context"
 )
 
 func TestValidateStepFunc(t *testing.T) {
 	testCases := map[string]interface{}{
 		"function without arguments":           func() {},
 		"function with 1 argument":             func(StepTest) {},
-		"function with invalid first argument": func(int, context.Context) {},
+		"function with invalid first argument": func(int, Context) {},
 	}
 
 	for name, testCase := range testCases {
@@ -23,13 +21,18 @@ func TestValidateStepFunc(t *testing.T) {
 }
 
 func TestValidateStepFunc_ValidFunction(t *testing.T) {
-	if err := validateStepFunc(func(StepTest, context.Context) {}); err != nil {
+	if err := validateStepFunc(func(StepTest, Context) {}); err != nil {
 		t.Errorf("the test should NOT fail for the function: %s", err)
 	}
 }
 
 func TestValidateStepFunc_ReturnContext(t *testing.T) {
-	if err := validateStepFunc(func(StepTest, context.Context) context.Context { return context.Context{} }); err != nil {
+	if err := validateStepFunc(func(StepTest, Context) Context { return Context{} }); err != nil {
 		t.Errorf("step function returning a context should NOT fail validation: %s", err)
 	}
 }
+
+// Used for context package backwards compatibility tests.
+func ValidateStepFunc(f interface{}) error {
+	return validateStepFunc(f)
+}