Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor integration test suite to use testify #589

Merged
merged 1 commit into from
Mar 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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}
gmfrasca marked this conversation as resolved.
Show resolved Hide resolved

##@ 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.")
DharmitD marked this conversation as resolved.
Show resolved Hide resolved
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
Loading