Repository: kyverno/chainsaw
Pull request #324 (2023-11-02 09:51:57)

fix: Add operations field in the TestStep
Fix : https://github.com/kyverno/chainsaw/issues/220

codecov[bot]: ## [Codecov](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) Report
> Merging [#324](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (059a80d) into [main](https://app.codecov.io/gh/kyverno/chainsaw/commit/87a9cc2ba736481ce69ea432c51cdb787a9f5100?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) (87a9cc2) will **increase** coverage by `0.07%`.
> The diff coverage is `22.22%`.

```diff
@@            Coverage Diff             @@
##             main     #324      +/-   ##
==========================================
+ Coverage   68.32%   68.39%   +0.07%     
==========================================
  Files          47       47              
  Lines        1733     1753      +20     
==========================================
+ Hits         1184     1199      +15     
- Misses        469      474       +5     
  Partials       80       80              
```


| [Files](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno) | Coverage Δ | |
|---|---|---|
| [pkg/discovery/load.go](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno#diff-cGtnL2Rpc2NvdmVyeS9sb2FkLmdv) | `87.87% <100.00%> (+1.21%)` | :arrow_up: |
| [pkg/commands/kuttl/migrate/command.go](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno#diff-cGtnL2NvbW1hbmRzL2t1dHRsL21pZ3JhdGUvY29tbWFuZC5nbw==) | `70.05% <57.14%> (+0.51%)` | :arrow_up: |
| [pkg/runner/step.go](https://app.codecov.io/gh/kyverno/chainsaw/pull/324?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno#diff-cGtnL3J1bm5lci9zdGVwLmdv) | `0.00% <0.00%> (ø)` | |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=kyverno)

eddycharly: Shouldn't we have an `executeOperation` func or something similar now ?

Patch:
diff --git a/pkg/apis/v1alpha1/operations.go b/pkg/apis/v1alpha1/operations.go
new file mode 100644
index 00000000..f205ce5a
--- /dev/null
+++ b/pkg/apis/v1alpha1/operations.go
@@ -0,0 +1,27 @@
+package v1alpha1
+
+type Operation struct {
+	// Assert represents the assertions to be made for this test step. It checks whether the conditions
+	// specified in each assertion hold true.
+	// +optional
+	Assert []Assert `json:"assert,omitempty"`
+
+	// Apply lists the resources that should be applied for this test step. This can include things
+	// like configuration settings or any other resources that need to be available during the test.
+	// +optional
+	Apply []Apply `json:"apply,omitempty"`
+
+	// Error lists the expected errors for this test step. If any of these errors occur, the test
+	// will consider them as expected; otherwise, they will be treated as test failures.
+	// +optional
+	Error []Error `json:"error,omitempty"`
+
+	// Delete provides a list of objects that should be deleted before this test step is executed.
+	// This helps in ensuring that the environment is set up correctly before the test step runs.
+	// +optional
+	Delete []Delete `json:"delete,omitempty"`
+
+	// Exec provides a list of commands and/or scripts that should be executed as a part of this test step.
+	// +optional
+	Exec []ExecOperation `json:"exec,omitempty"`
+}
diff --git a/pkg/apis/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
index 14518d59..3fa634c0 100644
--- a/pkg/apis/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/v1alpha1/zz_generated.deepcopy.go
@@ -396,6 +396,57 @@ func (in *OnFailure) DeepCopy() *OnFailure {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Operation) DeepCopyInto(out *Operation) {
+	*out = *in
+	if in.Assert != nil {
+		in, out := &in.Assert, &out.Assert
+		*out = make([]Assert, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Apply != nil {
+		in, out := &in.Apply, &out.Apply
+		*out = make([]Apply, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Error != nil {
+		in, out := &in.Error, &out.Error
+		*out = make([]Error, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Delete != nil {
+		in, out := &in.Delete, &out.Delete
+		*out = make([]Delete, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Exec != nil {
+		in, out := &in.Exec, &out.Exec
+		*out = make([]ExecOperation, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Operation.
+func (in *Operation) DeepCopy() *Operation {
+	if in == nil {
+		return nil
+	}
+	out := new(Operation)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *PodLogs) DeepCopyInto(out *PodLogs) {
 	*out = *in
@@ -552,37 +603,9 @@ func (in *TestStepSpec) DeepCopyInto(out *TestStepSpec) {
 		*out = new(bool)
 		**out = **in
 	}
-	if in.Assert != nil {
-		in, out := &in.Assert, &out.Assert
-		*out = make([]Assert, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Apply != nil {
-		in, out := &in.Apply, &out.Apply
-		*out = make([]Apply, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Error != nil {
-		in, out := &in.Error, &out.Error
-		*out = make([]Error, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Delete != nil {
-		in, out := &in.Delete, &out.Delete
-		*out = make([]Delete, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-	if in.Exec != nil {
-		in, out := &in.Exec, &out.Exec
-		*out = make([]ExecOperation, len(*in))
+	if in.Operations != nil {
+		in, out := &in.Operations, &out.Operations
+		*out = make([]Operation, len(*in))
 		for i := range *in {
 			(*in)[i].DeepCopyInto(&(*out)[i])
 		}
diff --git a/pkg/commands/kuttl/migrate/command.go b/pkg/commands/kuttl/migrate/command.go
index 0c16a9b0..1789eb44 100644
--- a/pkg/commands/kuttl/migrate/command.go
+++ b/pkg/commands/kuttl/migrate/command.go
@@ -192,17 +192,19 @@ func testStep(in unstructured.Unstructured) (*v1alpha1.TestStep, error) {
 		},
 		ObjectMeta: from.ObjectMeta,
 	}
+
+	singleOperation := v1alpha1.Operation{}
 	for _, operation := range from.Apply {
-		to.Spec.Apply = append(to.Spec.Apply, v1alpha1.Apply{FileRef: v1alpha1.FileRef{File: operation}})
+		singleOperation.Apply = append(singleOperation.Apply, v1alpha1.Apply{FileRef: v1alpha1.FileRef{File: operation}})
 	}
 	for _, operation := range from.Assert {
-		to.Spec.Assert = append(to.Spec.Assert, v1alpha1.Assert{FileRef: v1alpha1.FileRef{File: operation}})
+		singleOperation.Assert = append(singleOperation.Assert, v1alpha1.Assert{FileRef: v1alpha1.FileRef{File: operation}})
 	}
 	for _, operation := range from.Error {
-		to.Spec.Error = append(to.Spec.Error, v1alpha1.Error{FileRef: v1alpha1.FileRef{File: operation}})
+		singleOperation.Error = append(singleOperation.Error, v1alpha1.Error{FileRef: v1alpha1.FileRef{File: operation}})
 	}
 	for _, operation := range from.Delete {
-		to.Spec.Delete = append(to.Spec.Delete, v1alpha1.Delete{
+		singleOperation.Delete = append(singleOperation.Delete, v1alpha1.Delete{
 			ObjectReference: v1alpha1.ObjectReference{
 				APIVersion: operation.APIVersion,
 				Kind:       operation.Kind,
@@ -214,5 +216,6 @@ func testStep(in unstructured.Unstructured) (*v1alpha1.TestStep, error) {
 			},
 		})
 	}
+	to.Spec.Operations = append(to.Spec.Operations, singleOperation)
 	return to, nil
 }
diff --git a/pkg/discovery/load.go b/pkg/discovery/load.go
index 5a18ea4d..841f6942 100644
--- a/pkg/discovery/load.go
+++ b/pkg/discovery/load.go
@@ -117,16 +117,28 @@ func LoadTest(fileName string, path string) (*Test, error) {
 				}
 				switch groups[2] {
 				case "assert":
-					step.Spec.Assert = append(step.Spec.Assert, v1alpha1.Assert{
-						FileRef: fileRef,
+					step.Spec.Operations = append(step.Spec.Operations, v1alpha1.Operation{
+						Assert: []v1alpha1.Assert{
+							{
+								FileRef: fileRef,
+							},
+						},
 					})
 				case "error":
-					step.Spec.Error = append(step.Spec.Error, v1alpha1.Error{
-						FileRef: fileRef,
+					step.Spec.Operations = append(step.Spec.Operations, v1alpha1.Operation{
+						Error: []v1alpha1.Error{
+							{
+								FileRef: fileRef,
+							},
+						},
 					})
 				default:
-					step.Spec.Apply = append(step.Spec.Apply, v1alpha1.Apply{
-						FileRef: fileRef,
+					step.Spec.Operations = append(step.Spec.Operations, v1alpha1.Operation{
+						Apply: []v1alpha1.Apply{
+							{
+								FileRef: fileRef,
+							},
+						},
 					})
 				}
 				stepsMap[groups[1]] = step
diff --git a/pkg/runner/flags.go b/pkg/runner/internal/flags.go
similarity index 78%
rename from pkg/runner/flags.go
rename to pkg/runner/internal/flags.go
index 7f351c33..e7573dfe 100644
--- a/pkg/runner/flags.go
+++ b/pkg/runner/internal/flags.go
@@ -1,4 +1,4 @@
-package runner
+package internal
 
 import (
 	"flag"
@@ -8,7 +8,7 @@ import (
 	"github.com/kyverno/chainsaw/pkg/runner/flags"
 )
 
-func setupFlags(config v1alpha1.ConfigurationSpec) error {
+func SetupFlags(config v1alpha1.ConfigurationSpec) error {
 	testing.Init()
 	for k, v := range flags.GetFlags(config) {
 		if err := flag.Set(k, v); err != nil {
diff --git a/pkg/runner/runner.go b/pkg/runner/runner.go
index 0b2019ae..5da83d0f 100644
--- a/pkg/runner/runner.go
+++ b/pkg/runner/runner.go
@@ -12,6 +12,7 @@ import (
 	runnerclient "github.com/kyverno/chainsaw/pkg/runner/client"
 	"github.com/kyverno/chainsaw/pkg/runner/internal"
 	"github.com/kyverno/chainsaw/pkg/runner/logging"
+	"github.com/kyverno/chainsaw/pkg/runner/names"
 	"github.com/kyverno/chainsaw/pkg/runner/namespacer"
 	"github.com/kyverno/kyverno/ext/output/color"
 	"k8s.io/apimachinery/pkg/api/errors"
@@ -24,7 +25,7 @@ func Run(cfg *rest.Config, clock clock.PassiveClock, config v1alpha1.Configurati
 	if len(tests) == 0 {
 		return &summary, nil
 	}
-	if err := setupFlags(config); err != nil {
+	if err := internal.SetupFlags(config); err != nil {
 		return nil, err
 	}
 	c, err := client.New(cfg)
@@ -41,7 +42,7 @@ func Run(cfg *rest.Config, clock clock.PassiveClock, config v1alpha1.Configurati
 		Name: "chainsaw",
 		F: func(t *testing.T) {
 			t.Helper()
-			mainLogger := logging.NewLogger(t, clock, t.Name(), "@init")
+			mainLogger := logging.NewLogger(t, clock, t.Name(), "@main")
 			ctx := Context{
 				clock: clock,
 				clientFactory: func(logger logging.Logger) client.Client {
@@ -93,7 +94,7 @@ func Run(cfg *rest.Config, clock clock.PassiveClock, config v1alpha1.Configurati
 						size = len(name)
 					}
 				}
-				name, err := testName(config, test)
+				name, err := names.Test(config, test)
 				if err != nil {
 					mainLogger.Log("INTERN", color.BoldRed, err)
 					t.FailNow()
diff --git a/pkg/runner/step.go b/pkg/runner/step.go
index dd1d9e2b..def3d5f1 100644
--- a/pkg/runner/step.go
+++ b/pkg/runner/step.go
@@ -63,17 +63,38 @@ func executeStep(t *testing.T, logger logging.Logger, ctx Context, basePath stri
 			})
 		}
 	}()
-	for _, operation := range step.Spec.Delete {
-		var resource unstructured.Unstructured
-		resource.SetAPIVersion(operation.APIVersion)
-		resource.SetKind(operation.Kind)
-		resource.SetName(operation.Name)
-		resource.SetNamespace(operation.Namespace)
-		resource.SetLabels(operation.Labels)
-		if err := operationsClient.Delete(operation.Timeout, &resource); err != nil {
-			fail(t, operation.ContinueOnError)
+
+	for _, operation := range step.Spec.Operations {
+		executeOperation(t, logger, ctx, basePath, config, test, step, operation, operationsClient)
+	}
+}
+
+func executeOperation(t *testing.T, logger logging.Logger, ctx Context, basePath string, config v1alpha1.ConfigurationSpec, test v1alpha1.TestSpec, step v1alpha1.TestSpecStep, operation v1alpha1.Operation, operationsClient operations.Client) {
+	t.Helper()
+	// Handle Delete
+	if operation.Delete != nil {
+		for _, operation := range operation.Delete {
+			var resource unstructured.Unstructured
+			resource.SetAPIVersion(operation.APIVersion)
+			resource.SetKind(operation.Kind)
+			resource.SetName(operation.Name)
+			resource.SetNamespace(operation.Namespace)
+			resource.SetLabels(operation.Labels)
+			if err := operationsClient.Delete(operation.Timeout, &resource); err != nil {
+				fail(t, operation.ContinueOnError)
+			}
 		}
 	}
+
+	// Handle Exec
+	if operation.Exec != nil {
+		for _, operation := range operation.Exec {
+			if err := operationsClient.Exec(operation.Exec, !operation.SkipLogOutput, ctx.namespacer.GetNamespace()); err != nil {
+				fail(t, operation.ContinueOnError)
+			}
+		}
+	}
+
 	var doCleanup operations.CleanupFunc
 	if !cleanup.Skip(config.SkipDelete, test.SkipDelete, step.Spec.SkipDelete) {
 		doCleanup = func(obj ctrlclient.Object, c client.Client) {
@@ -84,47 +105,53 @@ func executeStep(t *testing.T, logger logging.Logger, ctx Context, basePath stri
 			})
 		}
 	}
-	for _, operation := range step.Spec.Exec {
-		if err := operationsClient.Exec(operation.Exec, !operation.SkipLogOutput, ctx.namespacer.GetNamespace()); err != nil {
-			fail(t, operation.ContinueOnError)
-		}
-	}
-	for _, operation := range step.Spec.Apply {
-		resources, err := resource.Load(filepath.Join(basePath, operation.File))
-		if err != nil {
-			logger.Log("LOAD  ", color.BoldRed, err)
-			fail(t, operation.ContinueOnError)
-		}
-		shouldFail := operation.ShouldFail != nil && *operation.ShouldFail
-		for i := range resources {
-			resource := &resources[i]
-			if err := operationsClient.Apply(operation.Timeout, resource, shouldFail, doCleanup); err != nil {
+	// Handle Apply
+	if operation.Apply != nil {
+		for _, operation := range operation.Apply {
+			resources, err := resource.Load(filepath.Join(basePath, operation.File))
+			if err != nil {
+				logger.Log("LOAD  ", color.BoldRed, err)
 				fail(t, operation.ContinueOnError)
 			}
+			shouldFail := operation.ShouldFail != nil && *operation.ShouldFail
+			for i := range resources {
+				resource := &resources[i]
+				if err := operationsClient.Apply(operation.Timeout, resource, shouldFail, doCleanup); err != nil {
+					fail(t, operation.ContinueOnError)
+				}
+			}
 		}
 	}
-	for _, operation := range step.Spec.Assert {
-		resources, err := resource.Load(filepath.Join(basePath, operation.File))
-		if err != nil {
-			logger.Log("LOAD  ", color.BoldRed, err)
-			fail(t, operation.ContinueOnError)
-		}
-		for _, resource := range resources {
-			if err := operationsClient.Assert(operation.Timeout, resource); err != nil {
+
+	// Handle Assert
+	if operation.Assert != nil {
+		for _, operation := range operation.Assert {
+			resources, err := resource.Load(filepath.Join(basePath, operation.File))
+			if err != nil {
+				logger.Log("LOAD  ", color.BoldRed, err)
 				fail(t, operation.ContinueOnError)
 			}
+			for _, resource := range resources {
+				if err := operationsClient.Assert(operation.Timeout, resource); err != nil {
+					fail(t, operation.ContinueOnError)
+				}
+			}
 		}
 	}
-	for _, operation := range step.Spec.Error {
-		resources, err := resource.Load(filepath.Join(basePath, operation.File))
-		if err != nil {
-			logger.Log("LOAD  ", color.BoldRed, err)
-			fail(t, operation.ContinueOnError)
-		}
-		for _, resource := range resources {
-			if err := operationsClient.Error(operation.Timeout, resource); err != nil {
+
+	// Handle Error
+	if operation.Error != nil {
+		for _, operation := range operation.Error {
+			resources, err := resource.Load(filepath.Join(basePath, operation.File))
+			if err != nil {
+				logger.Log("LOAD  ", color.BoldRed, err)
 				fail(t, operation.ContinueOnError)
 			}
+			for _, resource := range resources {
+				if err := operationsClient.Error(operation.Timeout, resource); err != nil {
+					fail(t, operation.ContinueOnError)
+				}
+			}
 		}
 	}
 }
diff --git a/website/docs/apis/chainsaw.v1alpha1.md b/website/docs/apis/chainsaw.v1alpha1.md
index 34920811..fcdbbac9 100644
--- a/website/docs/apis/chainsaw.v1alpha1.md
+++ b/website/docs/apis/chainsaw.v1alpha1.md
@@ -54,7 +54,7 @@ auto_generated: true
 
 **Appears in:**
     
-- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+- [Operation](#chainsaw-kyverno-io-v1alpha1-Operation)
 
 <p>Apply represents a set of configurations or resources that
 should be applied during testing.</p>
@@ -71,7 +71,7 @@ should be applied during testing.</p>
 
 **Appears in:**
     
-- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+- [Operation](#chainsaw-kyverno-io-v1alpha1-Operation)
 
 <p>Assert represents a test condition that is expected to hold true
 during the testing process.</p>
@@ -139,7 +139,7 @@ during the testing process.</p>
 
 **Appears in:**
     
-- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+- [Operation](#chainsaw-kyverno-io-v1alpha1-Operation)
 
 <p>Delete is a reference to an object that should be deleted</p>
 
@@ -154,7 +154,7 @@ during the testing process.</p>
 
 **Appears in:**
     
-- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+- [Operation](#chainsaw-kyverno-io-v1alpha1-Operation)
 
 <p>Error represents an anticipated error condition that may arise during testing.
 Instead of treating such an error as a test failure, it acknowledges it as expected.</p>
@@ -201,7 +201,7 @@ Instead of treating such an error as a test failure, it acknowledges it as expec
 
 **Appears in:**
     
-- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+- [Operation](#chainsaw-kyverno-io-v1alpha1-Operation)
 
 <p>Exec describes a command and/or script operation.</p>
 
@@ -275,6 +275,20 @@ For multiple objects use labels.</p>
 | `collect` | [`Collect`](#chainsaw-kyverno-io-v1alpha1-Collect) |  |  | <p>Collect define the collectors to run.</p> |
 | `exec` | [`Exec`](#chainsaw-kyverno-io-v1alpha1-Exec) |  |  | <p>Exec define the commands and/or scripts to run.</p> |
 
+## `Operation`     {#chainsaw-kyverno-io-v1alpha1-Operation}
+
+**Appears in:**
+    
+- [TestStepSpec](#chainsaw-kyverno-io-v1alpha1-TestStepSpec)
+
+| Field | Type | Required | Inline | Description |
+|---|---|---|---|---|
+| `assert` | [`[]Assert`](#chainsaw-kyverno-io-v1alpha1-Assert) |  |  | <p>Assert represents the assertions to be made for this test step. It checks whether the conditions specified in each assertion hold true.</p> |
+| `apply` | [`[]Apply`](#chainsaw-kyverno-io-v1alpha1-Apply) |  |  | <p>Apply lists the resources that should be applied for this test step. This can include things like configuration settings or any other resources that need to be available during the test.</p> |
+| `error` | [`[]Error`](#chainsaw-kyverno-io-v1alpha1-Error) |  |  | <p>Error lists the expected errors for this test step. If any of these errors occur, the test will consider them as expected; otherwise, they will be treated as test failures.</p> |
+| `delete` | [`[]Delete`](#chainsaw-kyverno-io-v1alpha1-Delete) |  |  | <p>Delete provides a list of objects that should be deleted before this test step is executed. This helps in ensuring that the environment is set up correctly before the test step runs.</p> |
+| `exec` | [`[]ExecOperation`](#chainsaw-kyverno-io-v1alpha1-ExecOperation) |  |  | <p>Exec provides a list of commands and/or scripts that should be executed as a part of this test step.</p> |
+
 ## `PodLogs`     {#chainsaw-kyverno-io-v1alpha1-PodLogs}
 
 **Appears in:**
@@ -359,11 +373,7 @@ For multiple objects use labels.</p>
 |---|---|---|---|---|
 | `timeouts` | [`Timeouts`](#chainsaw-kyverno-io-v1alpha1-Timeouts) |  |  | <p>Timeouts for the test step. Overrides the global timeouts set in the Configuration and the timeouts eventually set in the Test.</p> |
 | `skipDelete` | `bool` |  |  | <p>SkipDelete determines whether the resources created by the step should be deleted after the test step is executed.</p> |
-| `assert` | [`[]Assert`](#chainsaw-kyverno-io-v1alpha1-Assert) |  |  | <p>Assert represents the assertions to be made for this test step. It checks whether the conditions specified in each assertion hold true.</p> |
-| `apply` | [`[]Apply`](#chainsaw-kyverno-io-v1alpha1-Apply) |  |  | <p>Apply lists the resources that should be applied for this test step. This can include things like configuration settings or any other resources that need to be available during the test.</p> |
-| `error` | [`[]Error`](#chainsaw-kyverno-io-v1alpha1-Error) |  |  | <p>Error lists the expected errors for this test step. If any of these errors occur, the test will consider them as expected; otherwise, they will be treated as test failures.</p> |
-| `delete` | [`[]Delete`](#chainsaw-kyverno-io-v1alpha1-Delete) |  |  | <p>Delete provides a list of objects that should be deleted before this test step is executed. This helps in ensuring that the environment is set up correctly before the test step runs.</p> |
-| `exec` | [`[]ExecOperation`](#chainsaw-kyverno-io-v1alpha1-ExecOperation) |  |  | <p>Exec provides a list of commands and/or scripts that should be executed as a part of this test step.</p> |
+| `operations` | [`[]Operation`](#chainsaw-kyverno-io-v1alpha1-Operation) |  |  | <p>Operations defines the order in which the test step should be executed.</p> |
 | `onFailure` | [`[]OnFailure`](#chainsaw-kyverno-io-v1alpha1-OnFailure) |  |  | <p>OnFailure defines actions to be executed in case of step failure.</p> |
 
 ## `Timeouts`     {#chainsaw-kyverno-io-v1alpha1-Timeouts}


Test patch:
diff --git a/.crds/chainsaw.kyverno.io_tests.yaml b/.crds/chainsaw.kyverno.io_tests.yaml
index b0258361..0b84e76c 100644
--- a/.crds/chainsaw.kyverno.io_tests.yaml
+++ b/.crds/chainsaw.kyverno.io_tests.yaml
@@ -61,176 +61,6 @@ spec:
                     spec:
                       description: Spec of the step.
                       properties:
-                        apply:
-                          description: Apply lists the resources that should be applied
-                            for this test step. This can include things like configuration
-                            settings or any other resources that need to be available
-                            during the test.
-                          items:
-                            description: Apply represents a set of configurations
-                              or resources that should be applied during testing.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              shouldFail:
-                                description: ShouldFail determines whether applying
-                                  the file is expected to fail.
-                                type: boolean
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        assert:
-                          description: Assert represents the assertions to be made
-                            for this test step. It checks whether the conditions specified
-                            in each assertion hold true.
-                          items:
-                            description: Assert represents a test condition that is
-                              expected to hold true during the testing process.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        delete:
-                          description: Delete provides a list of objects that should
-                            be deleted before this test step is executed. This helps
-                            in ensuring that the environment is set up correctly before
-                            the test step runs.
-                          items:
-                            description: Delete is a reference to an object that should
-                              be deleted
-                            properties:
-                              apiVersion:
-                                description: API version of the referent.
-                                type: string
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              kind:
-                                description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                                type: string
-                              labels:
-                                additionalProperties:
-                                  type: string
-                                description: Label selector to match objects to delete
-                                type: object
-                              name:
-                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                                type: string
-                              namespace:
-                                description: 'Namespace of the referent. More info:
-                                  https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - apiVersion
-                            - kind
-                            type: object
-                          type: array
-                        error:
-                          description: Error lists the expected errors for this test
-                            step. If any of these errors occur, the test will consider
-                            them as expected; otherwise, they will be treated as test
-                            failures.
-                          items:
-                            description: Error represents an anticipated error condition
-                              that may arise during testing. Instead of treating such
-                              an error as a test failure, it acknowledges it as expected.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        exec:
-                          description: Exec provides a list of commands and/or scripts
-                            that should be executed as a part of this test step.
-                          items:
-                            description: Exec describes a command and/or script operation.
-                            properties:
-                              command:
-                                description: Command defines a command to run.
-                                properties:
-                                  args:
-                                    description: Args is the command arguments.
-                                    items:
-                                      type: string
-                                    type: array
-                                  entrypoint:
-                                    description: Entrypoint is the command entry point
-                                      to run.
-                                    type: string
-                                required:
-                                - entrypoint
-                                type: object
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              script:
-                                description: Script defines a script to run.
-                                properties:
-                                  content:
-                                    description: Content defines a shell script (run
-                                      with "sh -c ...").
-                                    type: string
-                                type: object
-                              skipLogOutput:
-                                description: SkipLogOutput removes the output from
-                                  the command. Useful for sensitive logs or to reduce
-                                  noise.
-                                type: boolean
-                              timeout:
-                                description: Timeout for the command. Overrides the
-                                  global timeout set in the Configuration.
-                                type: string
-                            type: object
-                          type: array
                         onFailure:
                           description: OnFailure defines actions to be executed in
                             case of step failure.
@@ -319,6 +149,198 @@ spec:
                                 type: object
                             type: object
                           type: array
+                        operations:
+                          description: Operations defines the order in which the test
+                            step should be executed.
+                          items:
+                            properties:
+                              apply:
+                                description: Apply lists the resources that should
+                                  be applied for this test step. This can include
+                                  things like configuration settings or any other
+                                  resources that need to be available during the test.
+                                items:
+                                  description: Apply represents a set of configurations
+                                    or resources that should be applied during testing.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    shouldFail:
+                                      description: ShouldFail determines whether applying
+                                        the file is expected to fail.
+                                      type: boolean
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              assert:
+                                description: Assert represents the assertions to be
+                                  made for this test step. It checks whether the conditions
+                                  specified in each assertion hold true.
+                                items:
+                                  description: Assert represents a test condition
+                                    that is expected to hold true during the testing
+                                    process.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              delete:
+                                description: Delete provides a list of objects that
+                                  should be deleted before this test step is executed.
+                                  This helps in ensuring that the environment is set
+                                  up correctly before the test step runs.
+                                items:
+                                  description: Delete is a reference to an object
+                                    that should be deleted
+                                  properties:
+                                    apiVersion:
+                                      description: API version of the referent.
+                                      type: string
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    kind:
+                                      description: 'Kind of the referent. More info:
+                                        https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                                      type: string
+                                    labels:
+                                      additionalProperties:
+                                        type: string
+                                      description: Label selector to match objects
+                                        to delete
+                                      type: object
+                                    name:
+                                      description: 'Name of the referent. More info:
+                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                      type: string
+                                    namespace:
+                                      description: 'Namespace of the referent. More
+                                        info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - apiVersion
+                                  - kind
+                                  type: object
+                                type: array
+                              error:
+                                description: Error lists the expected errors for this
+                                  test step. If any of these errors occur, the test
+                                  will consider them as expected; otherwise, they
+                                  will be treated as test failures.
+                                items:
+                                  description: Error represents an anticipated error
+                                    condition that may arise during testing. Instead
+                                    of treating such an error as a test failure, it
+                                    acknowledges it as expected.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              exec:
+                                description: Exec provides a list of commands and/or
+                                  scripts that should be executed as a part of this
+                                  test step.
+                                items:
+                                  description: Exec describes a command and/or script
+                                    operation.
+                                  properties:
+                                    command:
+                                      description: Command defines a command to run.
+                                      properties:
+                                        args:
+                                          description: Args is the command arguments.
+                                          items:
+                                            type: string
+                                          type: array
+                                        entrypoint:
+                                          description: Entrypoint is the command entry
+                                            point to run.
+                                          type: string
+                                      required:
+                                      - entrypoint
+                                      type: object
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    script:
+                                      description: Script defines a script to run.
+                                      properties:
+                                        content:
+                                          description: Content defines a shell script
+                                            (run with "sh -c ...").
+                                          type: string
+                                      type: object
+                                    skipLogOutput:
+                                      description: SkipLogOutput removes the output
+                                        from the command. Useful for sensitive logs
+                                        or to reduce noise.
+                                      type: boolean
+                                    timeout:
+                                      description: Timeout for the command. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  type: object
+                                type: array
+                            type: object
+                          type: array
                         skipDelete:
                           description: SkipDelete determines whether the resources
                             created by the step should be deleted after the test step
diff --git a/.crds/chainsaw.kyverno.io_teststeps.yaml b/.crds/chainsaw.kyverno.io_teststeps.yaml
index 89ca0e1b..424a961f 100644
--- a/.crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/.crds/chainsaw.kyverno.io_teststeps.yaml
@@ -35,169 +35,6 @@ spec:
           spec:
             description: TestStep spec.
             properties:
-              apply:
-                description: Apply lists the resources that should be applied for
-                  this test step. This can include things like configuration settings
-                  or any other resources that need to be available during the test.
-                items:
-                  description: Apply represents a set of configurations or resources
-                    that should be applied during testing.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    shouldFail:
-                      description: ShouldFail determines whether applying the file
-                        is expected to fail.
-                      type: boolean
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              assert:
-                description: Assert represents the assertions to be made for this
-                  test step. It checks whether the conditions specified in each assertion
-                  hold true.
-                items:
-                  description: Assert represents a test condition that is expected
-                    to hold true during the testing process.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              delete:
-                description: Delete provides a list of objects that should be deleted
-                  before this test step is executed. This helps in ensuring that the
-                  environment is set up correctly before the test step runs.
-                items:
-                  description: Delete is a reference to an object that should be deleted
-                  properties:
-                    apiVersion:
-                      description: API version of the referent.
-                      type: string
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    kind:
-                      description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                      type: string
-                    labels:
-                      additionalProperties:
-                        type: string
-                      description: Label selector to match objects to delete
-                      type: object
-                    name:
-                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                      type: string
-                    namespace:
-                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  type: object
-                type: array
-              error:
-                description: Error lists the expected errors for this test step. If
-                  any of these errors occur, the test will consider them as expected;
-                  otherwise, they will be treated as test failures.
-                items:
-                  description: Error represents an anticipated error condition that
-                    may arise during testing. Instead of treating such an error as
-                    a test failure, it acknowledges it as expected.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              exec:
-                description: Exec provides a list of commands and/or scripts that
-                  should be executed as a part of this test step.
-                items:
-                  description: Exec describes a command and/or script operation.
-                  properties:
-                    command:
-                      description: Command defines a command to run.
-                      properties:
-                        args:
-                          description: Args is the command arguments.
-                          items:
-                            type: string
-                          type: array
-                        entrypoint:
-                          description: Entrypoint is the command entry point to run.
-                          type: string
-                      required:
-                      - entrypoint
-                      type: object
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    script:
-                      description: Script defines a script to run.
-                      properties:
-                        content:
-                          description: Content defines a shell script (run with "sh
-                            -c ...").
-                          type: string
-                      type: object
-                    skipLogOutput:
-                      description: SkipLogOutput removes the output from the command.
-                        Useful for sensitive logs or to reduce noise.
-                      type: boolean
-                    timeout:
-                      description: Timeout for the command. Overrides the global timeout
-                        set in the Configuration.
-                      type: string
-                  type: object
-                type: array
               onFailure:
                 description: OnFailure defines actions to be executed in case of step
                   failure.
@@ -281,6 +118,180 @@ spec:
                       type: object
                   type: object
                 type: array
+              operations:
+                description: Operations defines the order in which the test step should
+                  be executed.
+                items:
+                  properties:
+                    apply:
+                      description: Apply lists the resources that should be applied
+                        for this test step. This can include things like configuration
+                        settings or any other resources that need to be available
+                        during the test.
+                      items:
+                        description: Apply represents a set of configurations or resources
+                          that should be applied during testing.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          shouldFail:
+                            description: ShouldFail determines whether applying the
+                              file is expected to fail.
+                            type: boolean
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    assert:
+                      description: Assert represents the assertions to be made for
+                        this test step. It checks whether the conditions specified
+                        in each assertion hold true.
+                      items:
+                        description: Assert represents a test condition that is expected
+                          to hold true during the testing process.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    delete:
+                      description: Delete provides a list of objects that should be
+                        deleted before this test step is executed. This helps in ensuring
+                        that the environment is set up correctly before the test step
+                        runs.
+                      items:
+                        description: Delete is a reference to an object that should
+                          be deleted
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Label selector to match objects to delete
+                            type: object
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - apiVersion
+                        - kind
+                        type: object
+                      type: array
+                    error:
+                      description: Error lists the expected errors for this test step.
+                        If any of these errors occur, the test will consider them
+                        as expected; otherwise, they will be treated as test failures.
+                      items:
+                        description: Error represents an anticipated error condition
+                          that may arise during testing. Instead of treating such
+                          an error as a test failure, it acknowledges it as expected.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    exec:
+                      description: Exec provides a list of commands and/or scripts
+                        that should be executed as a part of this test step.
+                      items:
+                        description: Exec describes a command and/or script operation.
+                        properties:
+                          command:
+                            description: Command defines a command to run.
+                            properties:
+                              args:
+                                description: Args is the command arguments.
+                                items:
+                                  type: string
+                                type: array
+                              entrypoint:
+                                description: Entrypoint is the command entry point
+                                  to run.
+                                type: string
+                            required:
+                            - entrypoint
+                            type: object
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          script:
+                            description: Script defines a script to run.
+                            properties:
+                              content:
+                                description: Content defines a shell script (run with
+                                  "sh -c ...").
+                                type: string
+                            type: object
+                          skipLogOutput:
+                            description: SkipLogOutput removes the output from the
+                              command. Useful for sensitive logs or to reduce noise.
+                            type: boolean
+                          timeout:
+                            description: Timeout for the command. Overrides the global
+                              timeout set in the Configuration.
+                            type: string
+                        type: object
+                      type: array
+                  type: object
+                type: array
               skipDelete:
                 description: SkipDelete determines whether the resources created by
                   the step should be deleted after the test step is executed.
diff --git a/pkg/apis/v1alpha1/test_step_spec.go b/pkg/apis/v1alpha1/test_step_spec.go
index 310634de..dfb62245 100644
--- a/pkg/apis/v1alpha1/test_step_spec.go
+++ b/pkg/apis/v1alpha1/test_step_spec.go
@@ -10,29 +10,9 @@ type TestStepSpec struct {
 	// +optional
 	SkipDelete *bool `json:"skipDelete,omitempty"`
 
-	// Assert represents the assertions to be made for this test step. It checks whether the conditions
-	// specified in each assertion hold true.
+	// Operations defines the order in which the test step should be executed.
 	// +optional
-	Assert []Assert `json:"assert,omitempty"`
-
-	// Apply lists the resources that should be applied for this test step. This can include things
-	// like configuration settings or any other resources that need to be available during the test.
-	// +optional
-	Apply []Apply `json:"apply,omitempty"`
-
-	// Error lists the expected errors for this test step. If any of these errors occur, the test
-	// will consider them as expected; otherwise, they will be treated as test failures.
-	// +optional
-	Error []Error `json:"error,omitempty"`
-
-	// Delete provides a list of objects that should be deleted before this test step is executed.
-	// This helps in ensuring that the environment is set up correctly before the test step runs.
-	// +optional
-	Delete []Delete `json:"delete,omitempty"`
-
-	// Exec provides a list of commands and/or scripts that should be executed as a part of this test step.
-	// +optional
-	Exec []ExecOperation `json:"exec,omitempty"`
+	Operations []Operation `json:"operations,omitempty"`
 
 	// OnFailure defines actions to be executed in case of step failure.
 	// +optional
diff --git a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
index b0258361..0b84e76c 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_tests.yaml
@@ -61,176 +61,6 @@ spec:
                     spec:
                       description: Spec of the step.
                       properties:
-                        apply:
-                          description: Apply lists the resources that should be applied
-                            for this test step. This can include things like configuration
-                            settings or any other resources that need to be available
-                            during the test.
-                          items:
-                            description: Apply represents a set of configurations
-                              or resources that should be applied during testing.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              shouldFail:
-                                description: ShouldFail determines whether applying
-                                  the file is expected to fail.
-                                type: boolean
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        assert:
-                          description: Assert represents the assertions to be made
-                            for this test step. It checks whether the conditions specified
-                            in each assertion hold true.
-                          items:
-                            description: Assert represents a test condition that is
-                              expected to hold true during the testing process.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        delete:
-                          description: Delete provides a list of objects that should
-                            be deleted before this test step is executed. This helps
-                            in ensuring that the environment is set up correctly before
-                            the test step runs.
-                          items:
-                            description: Delete is a reference to an object that should
-                              be deleted
-                            properties:
-                              apiVersion:
-                                description: API version of the referent.
-                                type: string
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              kind:
-                                description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                                type: string
-                              labels:
-                                additionalProperties:
-                                  type: string
-                                description: Label selector to match objects to delete
-                                type: object
-                              name:
-                                description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                                type: string
-                              namespace:
-                                description: 'Namespace of the referent. More info:
-                                  https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - apiVersion
-                            - kind
-                            type: object
-                          type: array
-                        error:
-                          description: Error lists the expected errors for this test
-                            step. If any of these errors occur, the test will consider
-                            them as expected; otherwise, they will be treated as test
-                            failures.
-                          items:
-                            description: Error represents an anticipated error condition
-                              that may arise during testing. Instead of treating such
-                              an error as a test failure, it acknowledges it as expected.
-                            properties:
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              file:
-                                description: File is the path to the referenced file.
-                                type: string
-                              timeout:
-                                description: Timeout for the operation. Overrides
-                                  the global timeout set in the Configuration.
-                                type: string
-                            required:
-                            - file
-                            type: object
-                          type: array
-                        exec:
-                          description: Exec provides a list of commands and/or scripts
-                            that should be executed as a part of this test step.
-                          items:
-                            description: Exec describes a command and/or script operation.
-                            properties:
-                              command:
-                                description: Command defines a command to run.
-                                properties:
-                                  args:
-                                    description: Args is the command arguments.
-                                    items:
-                                      type: string
-                                    type: array
-                                  entrypoint:
-                                    description: Entrypoint is the command entry point
-                                      to run.
-                                    type: string
-                                required:
-                                - entrypoint
-                                type: object
-                              continueOnError:
-                                description: ContinueOnError determines whether a
-                                  test should continue or not in case the operation
-                                  was not successful. Even if the test continues executing,
-                                  it will still be reported as failed.
-                                type: boolean
-                              script:
-                                description: Script defines a script to run.
-                                properties:
-                                  content:
-                                    description: Content defines a shell script (run
-                                      with "sh -c ...").
-                                    type: string
-                                type: object
-                              skipLogOutput:
-                                description: SkipLogOutput removes the output from
-                                  the command. Useful for sensitive logs or to reduce
-                                  noise.
-                                type: boolean
-                              timeout:
-                                description: Timeout for the command. Overrides the
-                                  global timeout set in the Configuration.
-                                type: string
-                            type: object
-                          type: array
                         onFailure:
                           description: OnFailure defines actions to be executed in
                             case of step failure.
@@ -319,6 +149,198 @@ spec:
                                 type: object
                             type: object
                           type: array
+                        operations:
+                          description: Operations defines the order in which the test
+                            step should be executed.
+                          items:
+                            properties:
+                              apply:
+                                description: Apply lists the resources that should
+                                  be applied for this test step. This can include
+                                  things like configuration settings or any other
+                                  resources that need to be available during the test.
+                                items:
+                                  description: Apply represents a set of configurations
+                                    or resources that should be applied during testing.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    shouldFail:
+                                      description: ShouldFail determines whether applying
+                                        the file is expected to fail.
+                                      type: boolean
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              assert:
+                                description: Assert represents the assertions to be
+                                  made for this test step. It checks whether the conditions
+                                  specified in each assertion hold true.
+                                items:
+                                  description: Assert represents a test condition
+                                    that is expected to hold true during the testing
+                                    process.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              delete:
+                                description: Delete provides a list of objects that
+                                  should be deleted before this test step is executed.
+                                  This helps in ensuring that the environment is set
+                                  up correctly before the test step runs.
+                                items:
+                                  description: Delete is a reference to an object
+                                    that should be deleted
+                                  properties:
+                                    apiVersion:
+                                      description: API version of the referent.
+                                      type: string
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    kind:
+                                      description: 'Kind of the referent. More info:
+                                        https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                                      type: string
+                                    labels:
+                                      additionalProperties:
+                                        type: string
+                                      description: Label selector to match objects
+                                        to delete
+                                      type: object
+                                    name:
+                                      description: 'Name of the referent. More info:
+                                        https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                                      type: string
+                                    namespace:
+                                      description: 'Namespace of the referent. More
+                                        info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - apiVersion
+                                  - kind
+                                  type: object
+                                type: array
+                              error:
+                                description: Error lists the expected errors for this
+                                  test step. If any of these errors occur, the test
+                                  will consider them as expected; otherwise, they
+                                  will be treated as test failures.
+                                items:
+                                  description: Error represents an anticipated error
+                                    condition that may arise during testing. Instead
+                                    of treating such an error as a test failure, it
+                                    acknowledges it as expected.
+                                  properties:
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    file:
+                                      description: File is the path to the referenced
+                                        file.
+                                      type: string
+                                    timeout:
+                                      description: Timeout for the operation. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  required:
+                                  - file
+                                  type: object
+                                type: array
+                              exec:
+                                description: Exec provides a list of commands and/or
+                                  scripts that should be executed as a part of this
+                                  test step.
+                                items:
+                                  description: Exec describes a command and/or script
+                                    operation.
+                                  properties:
+                                    command:
+                                      description: Command defines a command to run.
+                                      properties:
+                                        args:
+                                          description: Args is the command arguments.
+                                          items:
+                                            type: string
+                                          type: array
+                                        entrypoint:
+                                          description: Entrypoint is the command entry
+                                            point to run.
+                                          type: string
+                                      required:
+                                      - entrypoint
+                                      type: object
+                                    continueOnError:
+                                      description: ContinueOnError determines whether
+                                        a test should continue or not in case the
+                                        operation was not successful. Even if the
+                                        test continues executing, it will still be
+                                        reported as failed.
+                                      type: boolean
+                                    script:
+                                      description: Script defines a script to run.
+                                      properties:
+                                        content:
+                                          description: Content defines a shell script
+                                            (run with "sh -c ...").
+                                          type: string
+                                      type: object
+                                    skipLogOutput:
+                                      description: SkipLogOutput removes the output
+                                        from the command. Useful for sensitive logs
+                                        or to reduce noise.
+                                      type: boolean
+                                    timeout:
+                                      description: Timeout for the command. Overrides
+                                        the global timeout set in the Configuration.
+                                      type: string
+                                  type: object
+                                type: array
+                            type: object
+                          type: array
                         skipDelete:
                           description: SkipDelete determines whether the resources
                             created by the step should be deleted after the test step
diff --git a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
index 89ca0e1b..424a961f 100644
--- a/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
+++ b/pkg/data/crds/chainsaw.kyverno.io_teststeps.yaml
@@ -35,169 +35,6 @@ spec:
           spec:
             description: TestStep spec.
             properties:
-              apply:
-                description: Apply lists the resources that should be applied for
-                  this test step. This can include things like configuration settings
-                  or any other resources that need to be available during the test.
-                items:
-                  description: Apply represents a set of configurations or resources
-                    that should be applied during testing.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    shouldFail:
-                      description: ShouldFail determines whether applying the file
-                        is expected to fail.
-                      type: boolean
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              assert:
-                description: Assert represents the assertions to be made for this
-                  test step. It checks whether the conditions specified in each assertion
-                  hold true.
-                items:
-                  description: Assert represents a test condition that is expected
-                    to hold true during the testing process.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              delete:
-                description: Delete provides a list of objects that should be deleted
-                  before this test step is executed. This helps in ensuring that the
-                  environment is set up correctly before the test step runs.
-                items:
-                  description: Delete is a reference to an object that should be deleted
-                  properties:
-                    apiVersion:
-                      description: API version of the referent.
-                      type: string
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    kind:
-                      description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
-                      type: string
-                    labels:
-                      additionalProperties:
-                        type: string
-                      description: Label selector to match objects to delete
-                      type: object
-                    name:
-                      description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
-                      type: string
-                    namespace:
-                      description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - apiVersion
-                  - kind
-                  type: object
-                type: array
-              error:
-                description: Error lists the expected errors for this test step. If
-                  any of these errors occur, the test will consider them as expected;
-                  otherwise, they will be treated as test failures.
-                items:
-                  description: Error represents an anticipated error condition that
-                    may arise during testing. Instead of treating such an error as
-                    a test failure, it acknowledges it as expected.
-                  properties:
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    file:
-                      description: File is the path to the referenced file.
-                      type: string
-                    timeout:
-                      description: Timeout for the operation. Overrides the global
-                        timeout set in the Configuration.
-                      type: string
-                  required:
-                  - file
-                  type: object
-                type: array
-              exec:
-                description: Exec provides a list of commands and/or scripts that
-                  should be executed as a part of this test step.
-                items:
-                  description: Exec describes a command and/or script operation.
-                  properties:
-                    command:
-                      description: Command defines a command to run.
-                      properties:
-                        args:
-                          description: Args is the command arguments.
-                          items:
-                            type: string
-                          type: array
-                        entrypoint:
-                          description: Entrypoint is the command entry point to run.
-                          type: string
-                      required:
-                      - entrypoint
-                      type: object
-                    continueOnError:
-                      description: ContinueOnError determines whether a test should
-                        continue or not in case the operation was not successful.
-                        Even if the test continues executing, it will still be reported
-                        as failed.
-                      type: boolean
-                    script:
-                      description: Script defines a script to run.
-                      properties:
-                        content:
-                          description: Content defines a shell script (run with "sh
-                            -c ...").
-                          type: string
-                      type: object
-                    skipLogOutput:
-                      description: SkipLogOutput removes the output from the command.
-                        Useful for sensitive logs or to reduce noise.
-                      type: boolean
-                    timeout:
-                      description: Timeout for the command. Overrides the global timeout
-                        set in the Configuration.
-                      type: string
-                  type: object
-                type: array
               onFailure:
                 description: OnFailure defines actions to be executed in case of step
                   failure.
@@ -281,6 +118,180 @@ spec:
                       type: object
                   type: object
                 type: array
+              operations:
+                description: Operations defines the order in which the test step should
+                  be executed.
+                items:
+                  properties:
+                    apply:
+                      description: Apply lists the resources that should be applied
+                        for this test step. This can include things like configuration
+                        settings or any other resources that need to be available
+                        during the test.
+                      items:
+                        description: Apply represents a set of configurations or resources
+                          that should be applied during testing.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          shouldFail:
+                            description: ShouldFail determines whether applying the
+                              file is expected to fail.
+                            type: boolean
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    assert:
+                      description: Assert represents the assertions to be made for
+                        this test step. It checks whether the conditions specified
+                        in each assertion hold true.
+                      items:
+                        description: Assert represents a test condition that is expected
+                          to hold true during the testing process.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    delete:
+                      description: Delete provides a list of objects that should be
+                        deleted before this test step is executed. This helps in ensuring
+                        that the environment is set up correctly before the test step
+                        runs.
+                      items:
+                        description: Delete is a reference to an object that should
+                          be deleted
+                        properties:
+                          apiVersion:
+                            description: API version of the referent.
+                            type: string
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          kind:
+                            description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+                            type: string
+                          labels:
+                            additionalProperties:
+                              type: string
+                            description: Label selector to match objects to delete
+                            type: object
+                          name:
+                            description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
+                            type: string
+                          namespace:
+                            description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - apiVersion
+                        - kind
+                        type: object
+                      type: array
+                    error:
+                      description: Error lists the expected errors for this test step.
+                        If any of these errors occur, the test will consider them
+                        as expected; otherwise, they will be treated as test failures.
+                      items:
+                        description: Error represents an anticipated error condition
+                          that may arise during testing. Instead of treating such
+                          an error as a test failure, it acknowledges it as expected.
+                        properties:
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          file:
+                            description: File is the path to the referenced file.
+                            type: string
+                          timeout:
+                            description: Timeout for the operation. Overrides the
+                              global timeout set in the Configuration.
+                            type: string
+                        required:
+                        - file
+                        type: object
+                      type: array
+                    exec:
+                      description: Exec provides a list of commands and/or scripts
+                        that should be executed as a part of this test step.
+                      items:
+                        description: Exec describes a command and/or script operation.
+                        properties:
+                          command:
+                            description: Command defines a command to run.
+                            properties:
+                              args:
+                                description: Args is the command arguments.
+                                items:
+                                  type: string
+                                type: array
+                              entrypoint:
+                                description: Entrypoint is the command entry point
+                                  to run.
+                                type: string
+                            required:
+                            - entrypoint
+                            type: object
+                          continueOnError:
+                            description: ContinueOnError determines whether a test
+                              should continue or not in case the operation was not
+                              successful. Even if the test continues executing, it
+                              will still be reported as failed.
+                            type: boolean
+                          script:
+                            description: Script defines a script to run.
+                            properties:
+                              content:
+                                description: Content defines a shell script (run with
+                                  "sh -c ...").
+                                type: string
+                            type: object
+                          skipLogOutput:
+                            description: SkipLogOutput removes the output from the
+                              command. Useful for sensitive logs or to reduce noise.
+                            type: boolean
+                          timeout:
+                            description: Timeout for the command. Overrides the global
+                              timeout set in the Configuration.
+                            type: string
+                        type: object
+                      type: array
+                  type: object
+                type: array
               skipDelete:
                 description: SkipDelete determines whether the resources created by
                   the step should be deleted after the test step is executed.
diff --git a/pkg/discovery/discovery_test.go b/pkg/discovery/discovery_test.go
index 7f4dc456..5c5bb6c1 100644
--- a/pkg/discovery/discovery_test.go
+++ b/pkg/discovery/discovery_test.go
@@ -15,118 +15,142 @@ func TestDiscoverTests(t *testing.T) {
 		paths    []string
 		want     []Test
 		wantErr  bool
-	}{{
-		name:     "test",
-		fileName: "chainsaw-test.yaml",
-		paths:    []string{"../../testdata/discovery/test"},
-		want: []Test{{
-			BasePath: "../../testdata/discovery/test",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "test",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "create configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+	}{
+		{
+			name:     "test",
+			fileName: "chainsaw-test.yaml",
+			paths:    []string{"../../testdata/discovery/test"},
+			want: []Test{{
+				BasePath: "../../testdata/discovery/test",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "test",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "create configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}, {
-						Name: "assert configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+							},
+						}, {
+							Name: "assert configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
-				},
-			},
-		}},
-		wantErr: false,
-	}, {
-		name:     "manifests",
-		fileName: "chainsaw-test.yaml",
-		paths:    []string{"../../testdata/discovery/manifests"},
-		want: []Test{{
-			BasePath: "../../testdata/discovery/manifests",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
+							},
+						}},
+					},
 				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "manifests",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "assert",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-configmap.yaml",
-								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-assert.yaml",
+			}},
+			wantErr: false,
+		},
+		{
+			name:     "manifests",
+			fileName: "chainsaw-test.yaml",
+			paths:    []string{"../../testdata/discovery/manifests"},
+			want: []Test{{
+				BasePath: "../../testdata/discovery/manifests",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "manifests",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "assert",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-assert.yaml",
+											},
+										}},
+									},
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-configmap.yaml",
+											},
+										}},
+									},
+									{
+										Error: []v1alpha1.Error{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-error.yaml",
+											},
+										}},
+									},
 								},
-							}},
-							Error: []v1alpha1.Error{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-error.yaml",
-								},
-							}},
-						},
-					}},
-				},
-			},
-		}},
-		wantErr: false,
-	}, {
-		name:     "steps",
-		fileName: "chainsaw-test.yaml",
-		paths:    []string{"../../testdata/discovery/steps"},
-		want: []Test{{
-			BasePath: "../../testdata/discovery/steps",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "steps",
+							},
+						}},
+					},
 				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "test-1",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "foo.yaml",
+			}},
+			wantErr: false,
+		},
+		{
+			name:     "steps",
+			fileName: "chainsaw-test.yaml",
+			paths:    []string{"../../testdata/discovery/steps"},
+			want: []Test{{
+				BasePath: "../../testdata/discovery/steps",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "steps",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "test-1",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
+										}},
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "foo.yaml",
+											},
+										}},
+									},
 								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "bar.yaml",
-								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
-			},
-		}},
-		wantErr: false,
-	}}
+			}},
+			wantErr: false,
+		},
+	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			got, err := DiscoverTests(tt.fileName, tt.paths...)
diff --git a/pkg/discovery/load_test.go b/pkg/discovery/load_test.go
index 399837f8..5ee8ee25 100644
--- a/pkg/discovery/load_test.go
+++ b/pkg/discovery/load_test.go
@@ -18,251 +18,306 @@ func TestLoadTest(t *testing.T) {
 		path     string
 		want     *Test
 		wantErr  bool
-	}{{
-		name:     "invalid path",
-		fileName: "chainsaw-test.yaml",
-		path:     "/invalid",
-		want:     nil,
-		wantErr:  true,
-	}, {
-		name:     "no path",
-		fileName: "chainsaw-test.yaml",
-		path:     "",
-		want:     nil,
-		wantErr:  true,
-	}, {
-		name:     "test",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "test"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/test",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "test",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "create configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+	}{
+		{
+			name:     "invalid path",
+			fileName: "chainsaw-test.yaml",
+			path:     "/invalid",
+			want:     nil,
+			wantErr:  true,
+		},
+		{
+			name:     "no path",
+			fileName: "chainsaw-test.yaml",
+			path:     "",
+			want:     nil,
+			wantErr:  true,
+		},
+		{
+			name:     "test",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "test"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/test",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "test",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "create configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}, {
-						Name: "assert configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+							},
+						}, {
+							Name: "assert configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}, {
-		name:     "test",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "invalid-test-and-steps"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/invalid-test-and-steps",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "test",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "create configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+		{
+			name:     "test",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "invalid-test-and-steps"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/invalid-test-and-steps",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "test",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "create configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}, {
-						Name: "assert configmap",
-						Spec: v1alpha1.TestStepSpec{
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "configmap.yaml",
+							},
+						}, {
+							Name: "assert configmap",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "configmap.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}, {
-		name:     "test",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "test-and-steps"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/test-and-steps",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "test",
-				},
-				Spec: v1alpha1.TestSpec{
-					Skip:       ptr.To(false),
-					Concurrent: ptr.To(false),
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "test-1",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "foo.yaml",
-								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "bar.yaml",
+		{
+			name:     "test",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "test-and-steps"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/test-and-steps",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "test",
+					},
+					Spec: v1alpha1.TestSpec{
+						Skip:       ptr.To(false),
+						Concurrent: ptr.To(false),
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "test-1",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "foo.yaml",
+											},
+										}},
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}, {
-		name:     "steps",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "steps"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/steps",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "steps",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "test-1",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "foo.yaml",
-								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "bar.yaml",
+		{
+			name:     "steps",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "steps"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/steps",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "steps",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "test-1",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "foo.yaml",
+											},
+										}},
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}, {
-		name:     "steps",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "steps-and-manifests"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/steps-and-manifests",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "steps-and-manifests",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "test-1",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "foo.yaml",
-								},
-							}, {
-								FileRef: v1alpha1.FileRef{
-									File: "01-configmap.yaml",
-								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "bar.yaml",
-								},
-							}, {
-								FileRef: v1alpha1.FileRef{
-									File: "01-assert.yaml",
-								},
-							}},
-							Error: []v1alpha1.Error{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-error.yaml",
+		{
+			name:     "steps",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "steps-and-manifests"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/steps-and-manifests",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "steps-and-manifests",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "test-1",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "bar.yaml",
+											},
+										}},
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "foo.yaml",
+											},
+										}},
+									},
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-assert.yaml",
+											},
+										}},
+									},
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-configmap.yaml",
+											},
+										}},
+									},
+									{
+										Error: []v1alpha1.Error{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-error.yaml",
+											},
+										}},
+									},
 								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}, {
-		name:     "manifests",
-		fileName: "chainsaw-test.yaml",
-		path:     filepath.Join(basePath, "manifests"),
-		want: &Test{
-			BasePath: "../../testdata/discovery/manifests",
-			Test: &v1alpha1.Test{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: "chainsaw.kyverno.io/v1alpha1",
-					Kind:       "Test",
-				},
-				ObjectMeta: metav1.ObjectMeta{
-					Name: "manifests",
-				},
-				Spec: v1alpha1.TestSpec{
-					Steps: []v1alpha1.TestSpecStep{{
-						Name: "assert",
-						Spec: v1alpha1.TestStepSpec{
-							Apply: []v1alpha1.Apply{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-configmap.yaml",
-								},
-							}},
-							Assert: []v1alpha1.Assert{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-assert.yaml",
+		{
+			name:     "manifests",
+			fileName: "chainsaw-test.yaml",
+			path:     filepath.Join(basePath, "manifests"),
+			want: &Test{
+				BasePath: "../../testdata/discovery/manifests",
+				Test: &v1alpha1.Test{
+					TypeMeta: metav1.TypeMeta{
+						APIVersion: "chainsaw.kyverno.io/v1alpha1",
+						Kind:       "Test",
+					},
+					ObjectMeta: metav1.ObjectMeta{
+						Name: "manifests",
+					},
+					Spec: v1alpha1.TestSpec{
+						Steps: []v1alpha1.TestSpecStep{{
+							Name: "assert",
+							Spec: v1alpha1.TestStepSpec{
+								Operations: []v1alpha1.Operation{
+									{
+										Assert: []v1alpha1.Assert{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-assert.yaml",
+											},
+										}},
+									},
+									{
+										Apply: []v1alpha1.Apply{{
+											FileRef: v1alpha1.FileRef{
+												File: "01-configmap.yaml",
+											},
+										}},
+									},
+									{
+										Error: []v1alpha1.Error{
+											{
+												FileRef: v1alpha1.FileRef{
+													File: "01-error.yaml",
+												},
+											},
+										},
+									},
 								},
-							}},
-							Error: []v1alpha1.Error{{
-								FileRef: v1alpha1.FileRef{
-									File: "01-error.yaml",
-								},
-							}},
-						},
-					}},
+							},
+						}},
+					},
 				},
 			},
+			wantErr: false,
 		},
-		wantErr: false,
-	}}
+	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			got, err := LoadTest(tt.fileName, tt.path)
diff --git a/pkg/runner/test.go b/pkg/runner/names/test.go
similarity index 87%
rename from pkg/runner/test.go
rename to pkg/runner/names/test.go
index 4e48da18..0d305121 100644
--- a/pkg/runner/test.go
+++ b/pkg/runner/names/test.go
@@ -1,4 +1,4 @@
-package runner
+package names
 
 import (
 	"errors"
@@ -10,7 +10,7 @@ import (
 	"github.com/kyverno/chainsaw/pkg/discovery"
 )
 
-func testName(config v1alpha1.ConfigurationSpec, test discovery.Test) (string, error) {
+func Test(config v1alpha1.ConfigurationSpec, test discovery.Test) (string, error) {
 	if test.Test == nil {
 		return "", errors.New("test must not be nil")
 	}
diff --git a/pkg/runner/test_test.go b/pkg/runner/names/test_test.go
similarity index 95%
rename from pkg/runner/test_test.go
rename to pkg/runner/names/test_test.go
index f70fa390..1e577e93 100644
--- a/pkg/runner/test_test.go
+++ b/pkg/runner/names/test_test.go
@@ -1,4 +1,4 @@
-package runner
+package names
 
 import (
 	"os"
@@ -11,7 +11,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-func Test_testName(t *testing.T) {
+func TestTest(t *testing.T) {
 	cwd, err := os.Getwd()
 	assert.NoError(t, err)
 	tests := []struct {
@@ -93,7 +93,7 @@ func Test_testName(t *testing.T) {
 	}}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			got, err := testName(tt.config, tt.test)
+			got, err := Test(tt.config, tt.test)
 			if tt.wantErr {
 				assert.Error(t, err)
 			} else {
diff --git a/pkg/step/load_test.go b/pkg/step/load_test.go
index def3687f..649433c9 100644
--- a/pkg/step/load_test.go
+++ b/pkg/step/load_test.go
@@ -55,16 +55,20 @@ func TestLoad(t *testing.T) {
 						Name: "test-1",
 					},
 					Spec: v1alpha1.TestStepSpec{
-						Apply: []v1alpha1.Apply{{
-							FileRef: v1alpha1.FileRef{
-								File: "foo.yaml",
+						Operations: []v1alpha1.Operation{
+							{
+								Apply: []v1alpha1.Apply{{
+									FileRef: v1alpha1.FileRef{
+										File: "foo.yaml",
+									},
+								}},
+								Assert: []v1alpha1.Assert{{
+									FileRef: v1alpha1.FileRef{
+										File: "bar.yaml",
+									},
+								}},
 							},
-						}},
-						Assert: []v1alpha1.Assert{{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
-							},
-						}},
+						},
 					},
 				},
 			},
@@ -82,16 +86,20 @@ func TestLoad(t *testing.T) {
 						Name: "test-1",
 					},
 					Spec: v1alpha1.TestStepSpec{
-						Apply: []v1alpha1.Apply{{
-							FileRef: v1alpha1.FileRef{
-								File: "foo.yaml",
-							},
-						}},
-						Assert: []v1alpha1.Assert{{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+						Operations: []v1alpha1.Operation{
+							{
+								Apply: []v1alpha1.Apply{{
+									FileRef: v1alpha1.FileRef{
+										File: "foo.yaml",
+									},
+								}},
+								Assert: []v1alpha1.Assert{{
+									FileRef: v1alpha1.FileRef{
+										File: "bar.yaml",
+									},
+								}},
 							},
-						}},
+						},
 					},
 				},
 				{
@@ -103,16 +111,20 @@ func TestLoad(t *testing.T) {
 						Name: "test-2",
 					},
 					Spec: v1alpha1.TestStepSpec{
-						Apply: []v1alpha1.Apply{{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
-							},
-						}},
-						Assert: []v1alpha1.Assert{{
-							FileRef: v1alpha1.FileRef{
-								File: "foo.yaml",
+						Operations: []v1alpha1.Operation{
+							{
+								Apply: []v1alpha1.Apply{{
+									FileRef: v1alpha1.FileRef{
+										File: "bar.yaml",
+									},
+								}},
+								Assert: []v1alpha1.Assert{{
+									FileRef: v1alpha1.FileRef{
+										File: "foo.yaml",
+									},
+								}},
 							},
-						}},
+						},
 					},
 				},
 			},
diff --git a/pkg/test/load_test.go b/pkg/test/load_test.go
index 8c579ecb..61f67521 100644
--- a/pkg/test/load_test.go
+++ b/pkg/test/load_test.go
@@ -54,19 +54,27 @@ func TestLoad(t *testing.T) {
 			Spec: v1alpha1.TestSpec{
 				Steps: []v1alpha1.TestSpecStep{{
 					Spec: v1alpha1.TestStepSpec{
-						Apply: []v1alpha1.Apply{{
-							FileRef: v1alpha1.FileRef{
-								File: "foo.yaml",
+						Operations: []v1alpha1.Operation{
+							{
+								Apply: []v1alpha1.Apply{{
+									FileRef: v1alpha1.FileRef{
+										File: "foo.yaml",
+									},
+								}},
 							},
-						}},
+						},
 					},
 				}, {
 					Spec: v1alpha1.TestStepSpec{
-						Assert: []v1alpha1.Assert{{
-							FileRef: v1alpha1.FileRef{
-								File: "bar.yaml",
+						Operations: []v1alpha1.Operation{
+							{
+								Assert: []v1alpha1.Assert{{
+									FileRef: v1alpha1.FileRef{
+										File: "bar.yaml",
+									},
+								}},
 							},
-						}},
+						},
 					},
 				}},
 			},
diff --git a/testdata/discovery/invalid-test-and-steps/01-test.yaml b/testdata/discovery/invalid-test-and-steps/01-test.yaml
index b4cf1e1a..8a94cd3e 100644
--- a/testdata/discovery/invalid-test-and-steps/01-test.yaml
+++ b/testdata/discovery/invalid-test-and-steps/01-test.yaml
@@ -3,7 +3,8 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations:
+    - apply:
+        - file: foo.yaml
+    - assert:
+        - file: bar.yaml
diff --git a/testdata/discovery/invalid-test-and-steps/chainsaw-test.yaml b/testdata/discovery/invalid-test-and-steps/chainsaw-test.yaml
index 6bddbc0f..0a159f5e 100644
--- a/testdata/discovery/invalid-test-and-steps/chainsaw-test.yaml
+++ b/testdata/discovery/invalid-test-and-steps/chainsaw-test.yaml
@@ -6,9 +6,11 @@ spec:
   steps:
   - name: create configmap
     spec:
-      apply:
-      - file: configmap.yaml
+      operations:
+      - apply:
+        - file: configmap.yaml
   - name: assert configmap
     spec:
-      assert:
-      - file: configmap.yaml
+      operations:
+      - assert:
+        - file: configmap.yaml
diff --git a/testdata/discovery/steps-and-manifests/01-test.yaml b/testdata/discovery/steps-and-manifests/01-test.yaml
index b4cf1e1a..36e2af5b 100644
--- a/testdata/discovery/steps-and-manifests/01-test.yaml
+++ b/testdata/discovery/steps-and-manifests/01-test.yaml
@@ -3,7 +3,8 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations:
+    - apply:
+        - file: foo.yaml
+      assert:
+        - file: bar.yaml
diff --git a/testdata/discovery/steps/01-test.yaml b/testdata/discovery/steps/01-test.yaml
index b4cf1e1a..36e2af5b 100644
--- a/testdata/discovery/steps/01-test.yaml
+++ b/testdata/discovery/steps/01-test.yaml
@@ -3,7 +3,8 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations:
+    - apply:
+        - file: foo.yaml
+      assert:
+        - file: bar.yaml
diff --git a/testdata/discovery/test-and-steps/01-test.yaml b/testdata/discovery/test-and-steps/01-test.yaml
index b4cf1e1a..36e2af5b 100644
--- a/testdata/discovery/test-and-steps/01-test.yaml
+++ b/testdata/discovery/test-and-steps/01-test.yaml
@@ -3,7 +3,8 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations:
+    - apply:
+        - file: foo.yaml
+      assert:
+        - file: bar.yaml
diff --git a/testdata/discovery/test/chainsaw-test.yaml b/testdata/discovery/test/chainsaw-test.yaml
index 6bddbc0f..8ea00b1f 100644
--- a/testdata/discovery/test/chainsaw-test.yaml
+++ b/testdata/discovery/test/chainsaw-test.yaml
@@ -4,11 +4,13 @@ metadata:
   name: test
 spec:
   steps:
-  - name: create configmap
-    spec:
-      apply:
-      - file: configmap.yaml
-  - name: assert configmap
-    spec:
-      assert:
-      - file: configmap.yaml
+    - name: create configmap
+      spec:
+        operations:
+          - apply:
+              - file: configmap.yaml
+    - name: assert configmap
+      spec:
+        operations:
+          - assert:
+              - file: configmap.yaml
diff --git a/testdata/kuttl/01-step.chainsaw.yaml b/testdata/kuttl/01-step.chainsaw.yaml
index c25a05ba..1091a70c 100755
--- a/testdata/kuttl/01-step.chainsaw.yaml
+++ b/testdata/kuttl/01-step.chainsaw.yaml
@@ -5,14 +5,15 @@ metadata:
   creationTimestamp: null
   name: step
 spec:
-  delete:
-  - apiVersion: v1
-    kind: Pod
-    name: my-pod
-  - apiVersion: v1
-    kind: Pod
-    labels:
-      app: nginx
-  - apiVersion: v1
-    kind: Pod
+  operations:
+  - delete:
+    - apiVersion: v1
+      kind: Pod
+      name: my-pod
+    - apiVersion: v1
+      kind: Pod
+      labels:
+        app: nginx
+    - apiVersion: v1
+      kind: Pod
   timeouts: {}
diff --git a/testdata/step/multiple.yaml b/testdata/step/multiple.yaml
index 2dc735e7..c47fedad 100644
--- a/testdata/step/multiple.yaml
+++ b/testdata/step/multiple.yaml
@@ -3,10 +3,11 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations:
+  - apply:
+    - file: foo.yaml
+    assert:
+    - file: bar.yaml
 
 ---
 apiVersion: chainsaw.kyverno.io/v1alpha1
@@ -14,7 +15,8 @@ kind: TestStep
 metadata:
   name: test-2
 spec:
-  apply:
-  - file: bar.yaml
-  assert:
-  - file: foo.yaml
+  operations:
+  - apply:
+    - file: bar.yaml
+    assert:
+    - file: foo.yaml
diff --git a/testdata/step/ok.yaml b/testdata/step/ok.yaml
index b4cf1e1a..d05b5f45 100644
--- a/testdata/step/ok.yaml
+++ b/testdata/step/ok.yaml
@@ -3,7 +3,8 @@ kind: TestStep
 metadata:
   name: test-1
 spec:
-  apply:
-  - file: foo.yaml
-  assert:
-  - file: bar.yaml
+  operations: 
+  - apply:
+    - file: foo.yaml
+    assert:
+    - file: bar.yaml
diff --git a/testdata/test/ok.yaml b/testdata/test/ok.yaml
index 043f8089..e647c4d8 100644
--- a/testdata/test/ok.yaml
+++ b/testdata/test/ok.yaml
@@ -5,8 +5,10 @@ metadata:
 spec:
   steps:
   - spec:
-      apply:
-      - file: foo.yaml
+      operations:
+      - apply:
+        - file: foo.yaml
   - spec:
-      assert:
-      - file: bar.yaml
+      operations:
+      - assert:
+        - file: bar.yaml