Skip to content

Commit

Permalink
Refactor integration test suite to use testify
Browse files Browse the repository at this point in the history
  • Loading branch information
DharmitD committed Mar 18, 2024
1 parent eb6fe14 commit a835902
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 166 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ functest: manifests generate fmt vet envtest ## Run tests.
.PHONY: integrationtest
integrationtest: ## Run integration tests
cd tests && \
go run github.com/onsi/ginkgo/v2/ginkgo --tags=test_integration -- -kubeconfig=${KUBECONFIGPATH} -k8sApiServerHost=${K8SAPISERVERHOST} -DSPANamespace=${DSPANAMESPACE} -DSPAPath=${DSPAPATH} -ginkgo.v
go test ./... --tags=test_integration -v -kubeconfig=${KUBECONFIGPATH} -k8sApiServerHost=${K8SAPISERVERHOST} -DSPANamespace=${DSPANAMESPACE} -DSPAPath=${DSPAPATH}

##@ Build

Expand Down
8 changes: 4 additions & 4 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,12 @@ For the impatient developer, you can use the following flag to skip DSPA install
changes to a live environment and run the tests against it:

```bash
go run github.com/onsi/ginkgo/v2/ginkgo --tags=test_integration -- \
go test ./... --tags=test_integration -v \
-kubeconfig=${KUBECONFIG_PATH} \
-k8sApiServerHost=${TARGET_CLUSTER} \
-DSPANamespace=${TARGET_NAMESPACE} -DSPAPath=resources/dspa-lite.yaml \
-ginkgo.v
-skipDeploy=true
-DSPANamespace=${TARGET_NAMESPACE} \
-DSPAPath=resources/dspa-lite.yaml
-skipDeploy=true \
-skipCleanup=true
```

Expand Down
54 changes: 26 additions & 28 deletions tests/dspa_v2_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,42 +20,40 @@ package integration

import (
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
systemsTesttUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
"testing"

testUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

var _ = Describe("A successfully deployed DSPA", func() {

func (suite *IntegrationTestSuite) TestDSPADeployment() {
podCount := 8

Context("with default MariaDB and Minio", func() {
It(fmt.Sprintf("should have %d pods", podCount), func() {
suite.T().Run("with default MariaDB and Minio", func(t *testing.T) {
t.Run(fmt.Sprintf("should have %d pods", podCount), func(t *testing.T) {
podList := &corev1.PodList{}
listOpts := []client.ListOption{
client.InNamespace(DSPANamespace),
client.InNamespace(suite.DSPANamespace),
}
err := clientmgr.k8sClient.List(ctx, podList, listOpts...)
Expect(err).ToNot(HaveOccurred())
Expect(len(podList.Items)).Should(Equal(podCount))
err := suite.Clientmgr.k8sClient.List(suite.Ctx, podList, listOpts...)
require.NoError(t, err)
assert.Equal(t, podCount, len(podList.Items))
})

It(fmt.Sprintf("should have a ready %s deployment", "DSP API Server"), func() {
systemsTesttUtil.TestForSuccessfulDeployment(ctx, DSPANamespace, fmt.Sprintf("ds-pipeline-%s", DSPA.Name), clientmgr.k8sClient)
})
It(fmt.Sprintf("should have a ready %s deployment", "Persistence Agent"), func() {
systemsTesttUtil.TestForSuccessfulDeployment(ctx, DSPANamespace, fmt.Sprintf("ds-pipeline-persistenceagent-%s", DSPA.Name), clientmgr.k8sClient)
})
It(fmt.Sprintf("should have a ready %s deployment", "Scheduled Workflow"), func() {
systemsTesttUtil.TestForSuccessfulDeployment(ctx, DSPANamespace, fmt.Sprintf("ds-pipeline-scheduledworkflow-%s", DSPA.Name), clientmgr.k8sClient)
})
It(fmt.Sprintf("should have a ready %s deployment", "MariaDB"), func() {
systemsTesttUtil.TestForSuccessfulDeployment(ctx, DSPANamespace, fmt.Sprintf("mariadb-%s", DSPA.Name), clientmgr.k8sClient)
})
It(fmt.Sprintf("should have a ready %s deployment", "Minio"), func() {
systemsTesttUtil.TestForSuccessfulDeployment(ctx, DSPANamespace, fmt.Sprintf("minio-%s", DSPA.Name), clientmgr.k8sClient)
})
deployments := []string{
fmt.Sprintf("ds-pipeline-%s", suite.DSPA.Name),
fmt.Sprintf("ds-pipeline-persistenceagent-%s", suite.DSPA.Name),
fmt.Sprintf("ds-pipeline-scheduledworkflow-%s", suite.DSPA.Name),
fmt.Sprintf("mariadb-%s", suite.DSPA.Name),
fmt.Sprintf("minio-%s", suite.DSPA.Name),
}

for _, deployment := range deployments {
t.Run(fmt.Sprintf("should have a ready %s deployment", deployment), func(t *testing.T) {
testUtil.TestForSuccessfulDeployment(t, suite.Ctx, suite.DSPANamespace, deployment, suite.Clientmgr.k8sClient)
})
}
})
})
}
22 changes: 12 additions & 10 deletions tests/experiments_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,23 @@ package integration

import (
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"io/ioutil"
"net/http"
"testing"

"github.com/stretchr/testify/require"
)

var _ = Describe("A successfully deployed DSPA", func() {
It("Should successfully fetch experiments.", func() {
func (suite *IntegrationTestSuite) TestFetchExperiments() {
suite.T().Run("Should successfully fetch experiments", func(t *testing.T) {
response, err := http.Get(fmt.Sprintf("%s/apis/v2beta1/experiments", APIServerURL))
Expect(err).ToNot(HaveOccurred())
responseData, err := ioutil.ReadAll(response.Body)
loggr.Info(string(responseData))
require.NoError(t, err, "Error fetching experiments")

Expect(err).ToNot(HaveOccurred())
Expect(response.StatusCode).To(Equal(200))
responseData, err := ioutil.ReadAll(response.Body)
defer response.Body.Close()
require.NoError(t, err, "Error reading response body")

suite.Assert().Equal(200, response.StatusCode, "Expected HTTP status code 200 for fetching experiments")
loggr.Info(string(responseData))
})
})
}
30 changes: 16 additions & 14 deletions tests/pipeline_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,39 @@ package integration

import (
"fmt"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
systemsTesttUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
"io/ioutil"
"net/http"
"testing"

TestUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

var _ = Describe("A successfully deployed API Server", func() {
It("Should successfully fetch pipelines.", func() {
func (suite *IntegrationTestSuite) TestAPIServerDeployment() {
suite.T().Run("Should successfully fetch pipelines", func(t *testing.T) {
response, err := http.Get(fmt.Sprintf("%s/apis/v2beta1/pipelines", APIServerURL))
Expect(err).ToNot(HaveOccurred())
require.NoError(t, err)

responseData, err := ioutil.ReadAll(response.Body)
Expect(err).ToNot(HaveOccurred())
Expect(response.StatusCode).To(Equal(200))
require.NoError(t, err)
assert.Equal(t, 200, response.StatusCode)
loggr.Info(string(responseData))
})

It("Should successfully upload a pipeline.", func() {
suite.T().Run("Should successfully upload a pipeline", func(t *testing.T) {
postUrl := fmt.Sprintf("%s/apis/v2beta1/pipelines/upload", APIServerURL)
vals := map[string]string{
"uploadfile": "@resources/test-pipeline-run.yaml",
}
body, contentType := systemsTesttUtil.FormFromFile(vals)
body, contentType := TestUtil.FormFromFile(t, vals)

response, err := http.Post(postUrl, contentType, body)
Expect(err).ToNot(HaveOccurred())
require.NoError(t, err)
responseData, err := ioutil.ReadAll(response.Body)
responseString := string(responseData)
loggr.Info(responseString)
Expect(err).ToNot(HaveOccurred())
Expect(response.StatusCode).To(Equal(200))
require.NoError(t, err)
assert.Equal(t, 200, response.StatusCode)
})
})
}
128 changes: 66 additions & 62 deletions tests/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ import (
"context"
"flag"
"fmt"
"testing"
"time"

"github.com/stretchr/testify/assert"

"github.com/anthhub/forwarder"
"github.com/go-logr/logr"
mfc "github.com/manifestival/controller-runtime-client"
mf "github.com/manifestival/manifestival"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
dspav1alpha1 "github.com/opendatahub-io/data-science-pipelines-operator/api/v1alpha1"
systemsTesttUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
testUtil "github.com/opendatahub-io/data-science-pipelines-operator/tests/util"
"github.com/stretchr/testify/suite"
"go.uber.org/zap/zapcore"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes/scheme"
Expand All @@ -38,12 +42,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"testing"
"time"
)

const (
APIServerPort = 8888
)

var (
Expand Down Expand Up @@ -72,6 +70,7 @@ var (
)

const (
APIServerPort = 8888
DefaultKubeConfigPath = "~/.kube/config"
Defaultk8sApiServerHost = "localhost:6443"
DefaultDSPANamespace = "default"
Expand All @@ -90,19 +89,27 @@ type ClientManager struct {
mfopts mf.Option
}

// TestAPIs - This is the entry point for Ginkgo -
// the go test runner will run this function when you run go test or ginkgo.
// Under the hood, Ginkgo is simply calling go test.
// You can run go test instead of the ginkgo CLI, But Ginkgo has several capabilities that can only be accessed via ginkgo.
// It is best practice to embrace the ginkgo CLI and treat it as a first-class member of the testing toolchain.
func TestAPIs(t *testing.T) {
// Single line of glue code connecting Ginkgo to Gomega
// Inform our matcher library (Gomega) which function to call (Ginkgo's Fail) in the event a failure is detected.
RegisterFailHandler(Fail)

// Inform Ginkgo to start the test suite, passing it the *testing.T instance and a description of the suite.
// Only call RunSpecs once and let Ginkgo worry about calling *testing.T for us.
RunSpecs(t, "Controller Suite")
type IntegrationTestSuite struct {
suite.Suite
Clientmgr ClientManager
Ctx context.Context
DSPANamespace string
DSPA *dspav1alpha1.DataSciencePipelinesApplication
}

type testLogWriter struct {
t *testing.T
}

func (w *testLogWriter) Write(p []byte) (n int, err error) {
w.t.Log(string(p))
return len(p), nil
}

// newTestLogWriter creates a new instance of testLogWriter
// that adapts *testing.T to an io.Writer.
func newTestLogWriter(t *testing.T) *testLogWriter {
return &testLogWriter{t: t}
}

// Register flags in an init function. This ensures they are registered _before_ `go test` calls flag.Parse()
Expand All @@ -118,89 +125,86 @@ func init() {
PollInterval *= time.Second
flag.DurationVar(&DeleteTimeout, "DeleteTimeout", DefaultDeleteTimeout, "Seconds to wait for deployment deletions. Consider increasing this on resource starved environments.")
DeleteTimeout *= time.Second

flag.IntVar(&PortforwardLocalPort, "PortforwardLocalPort", DefaultPortforwardLocalPort, "Local port to use for port forwarding dspa server.")

flag.BoolVar(&skipDeploy, "skipDeploy", DefaultSkipDeploy, "Skip DSPA deployment. Use this if you have already "+
"manually deployed a DSPA, and want to skip this part.")
flag.BoolVar(&skipCleanup, "skipCleanup", DefaultSkipCleanup, "Skip DSPA cleanup.")
}

var _ = BeforeSuite(func() {
ctx, cancel = context.WithCancel(context.TODO())
func (suite *IntegrationTestSuite) SetupSuite() {
loggr = logf.Log
ctx, cancel = context.WithCancel(context.Background())
suite.Ctx = ctx

// Initialize logger
opts := zap.Options{
Development: true,
TimeEncoder: zapcore.TimeEncoderOfLayout(time.RFC3339),
}
logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseFlagOptions(&opts)))
logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(newTestLogWriter(suite.T())), zap.UseFlagOptions(&opts)))

loggr = logf.Log
var err error

// Register API objects
utilruntime.Must(dspav1alpha1.AddToScheme(scheme.Scheme))

clientmgr = ClientManager{}

// Set up client auth configs
cfg, err = clientcmd.BuildConfigFromFlags(k8sApiServerHost, kubeconfig)
Expect(err).ToNot(HaveOccurred())
suite.Require().NoError(err)

// Initialize Kubernetes client
clientmgr.k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme})
Expect(err).NotTo(HaveOccurred())
Expect(clientmgr.k8sClient).NotTo(BeNil())
suite.Require().NoError(err)
suite.Require().NotNil(clientmgr.k8sClient)
clientmgr.mfsClient = mfc.NewClient(clientmgr.k8sClient)
clientmgr.mfopts = mf.UseClient(clientmgr.mfsClient)
suite.Clientmgr = clientmgr

// Get DSPA structured
DSPA = systemsTesttUtil.GetDSPAFromPath(clientmgr.mfopts, DSPAPath)
DSPA = testUtil.GetDSPAFromPath(suite.T(), clientmgr.mfopts, DSPAPath)

suite.DSPANamespace = DSPANamespace
suite.DSPA = DSPA

if !skipDeploy {
loggr.Info("Deploying DSPA...")
systemsTesttUtil.DeployDSPA(ctx, clientmgr.k8sClient, DSPA, DSPANamespace, DeployTimeout, PollInterval)
err = testUtil.DeployDSPA(suite.T(), ctx, clientmgr.k8sClient, DSPA, DSPANamespace, DeployTimeout, PollInterval)
assert.NoError(suite.T(), err)
loggr.Info("Waiting for DSPA pods to ready...")
systemsTesttUtil.WaitForDSPAReady(ctx, clientmgr.k8sClient, DSPA.Name, DSPANamespace, DeployTimeout, PollInterval)
loggr.Info("DSPA Deployed.")
}

// Forward ApiServer Service
err = testUtil.WaitForDSPAReady(suite.T(), ctx, clientmgr.k8sClient, DSPA.Name, DSPANamespace, DeployTimeout, PollInterval)
assert.NoError(suite.T(), err)
loggr.Info("DSPA Deployed.")

loggr.Info("Setting up Portforwarding service.")
options := []*forwarder.Option{
{
// the local port for forwarding
LocalPort: PortforwardLocalPort,
// the k8s pod port
RemotePort: APIServerPort,
// the forwarding service name
LocalPort: PortforwardLocalPort,
RemotePort: APIServerPort,
ServiceName: fmt.Sprintf("ds-pipeline-%s", DSPA.Name),
// namespace default is "default"
Namespace: DSPANamespace,
Namespace: DSPANamespace,
},
}
// Create a forwarder, and provide a path to kubeconfig
forwarderResult, err = forwarder.WithForwarders(context.Background(), options, kubeconfig)
Expect(err).NotTo(HaveOccurred())
// wait forwarding ready

forwarderResult, err = forwarder.WithForwarders(ctx, options, kubeconfig)
suite.Require().NoError(err)
_, err = forwarderResult.Ready()
Expect(err).NotTo(HaveOccurred())
loggr.Info("Portforwarding service Successfully set up.")
suite.Require().NoError(err)

APIServerURL = fmt.Sprintf("http://127.0.0.1:%d", PortforwardLocalPort)
loggr.Info("Portforwarding service Successfully set up.")
}

loggr.Info("Starting Test Suite.")
})

var _ = BeforeEach(func() {
})

var _ = AfterSuite(func() {
func (suite *IntegrationTestSuite) TearDownSuite() {
if !skipCleanup {
systemsTesttUtil.DeleteDSPA(ctx, clientmgr.k8sClient, DSPA.Name, DSPANamespace, DeployTimeout, PollInterval)
err := testUtil.DeleteDSPA(suite.T(), ctx, clientmgr.k8sClient, DSPA.Name, DSPANamespace, DeployTimeout, PollInterval)
assert.NoError(suite.T(), err)
}
if forwarderResult != nil {
forwarderResult.Close()
}
})
cancel()
}

func TestIntegrationTestSuite(t *testing.T) {
suite.Run(t, new(IntegrationTestSuite))
}
Loading

0 comments on commit a835902

Please sign in to comment.