You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by zr...@apache.org on 2022/03/10 14:04:50 UTC

[trafficcontrol] branch master updated: Refactor about, asns, and acme tests (#6621)

This is an automated email from the ASF dual-hosted git repository.

zrhoffman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git


The following commit(s) were added to refs/heads/master by this push:
     new 6c54a9b  Refactor about, asns, and acme tests (#6621)
6c54a9b is described below

commit 6c54a9b592699882a3ef3a10d917e539f6f1a26b
Author: Eric Holguin <14...@users.noreply.github.com>
AuthorDate: Thu Mar 10 07:04:20 2022 -0700

    Refactor about, asns, and acme tests (#6621)
    
    * Refactored tests
    
    * Refactored tests
    
    * Added test data and test case structs
    
    * Updated tests to use TestCase struct from utils
---
 traffic_ops/testing/api/utils/utils.go         |  31 +++
 traffic_ops/testing/api/v3/about_test.go       |  36 ++-
 traffic_ops/testing/api/v3/asns_test.go        | 273 ++++++++++-------------
 traffic_ops/testing/api/v3/cachegroups_test.go | 116 +++++-----
 traffic_ops/testing/api/v4/about_test.go       |  36 ++-
 traffic_ops/testing/api/v4/acme_test.go        |  30 ++-
 traffic_ops/testing/api/v4/asns_test.go        | 294 +++++++++++--------------
 traffic_ops/testing/api/v4/cachegroups_test.go | 170 +++++++-------
 8 files changed, 484 insertions(+), 502 deletions(-)

diff --git a/traffic_ops/testing/api/utils/utils.go b/traffic_ops/testing/api/utils/utils.go
index eab8b1e..9fc854d 100644
--- a/traffic_ops/testing/api/utils/utils.go
+++ b/traffic_ops/testing/api/utils/utils.go
@@ -17,6 +17,8 @@ package utils
 
 import (
 	"encoding/json"
+	"net/http"
+	"net/url"
 	"reflect"
 	"sort"
 	"testing"
@@ -24,6 +26,8 @@ import (
 	"github.com/apache/trafficcontrol/lib/go-tc"
 	"github.com/apache/trafficcontrol/traffic_ops/testing/api/assert"
 	"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
+	v3client "github.com/apache/trafficcontrol/traffic_ops/v3-client"
+	v4client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
 )
 
 type ErrorAndMessage struct {
@@ -79,6 +83,33 @@ func Compare(t *testing.T, expected []string, alertsStrs []string) {
 	}
 }
 
+// V3TestCase is the type of the V3TestData struct.
+// Uses nested map to represent the method being tested and the test's description.
+type V3TestCase map[string]map[string]V3TestData
+
+// V4TestCase is the type of the V4TestData struct.
+// Uses nested map to represent the method being tested and the test's description.
+type V4TestCase map[string]map[string]V4TestData
+
+// V3TestData represents the data needed for testing the v3 api endpoints.
+type V3TestData struct {
+	EndpointId     func() int
+	ClientSession  *v3client.Session
+	RequestParams  url.Values
+	RequestHeaders http.Header
+	RequestBody    map[string]interface{}
+	Expectations   []CkReqFunc
+}
+
+// V4TestData represents the data needed for testing the v4 api endpoints.
+type V4TestData struct {
+	EndpointId    func() int
+	ClientSession *v4client.Session
+	RequestOpts   v4client.RequestOptions
+	RequestBody   map[string]interface{}
+	Expectations  []CkReqFunc
+}
+
 // CkReqFunc defines the reusable signature for all other functions that perform checks.
 // Common parameters that are checked include the request's info, response, alerts, and errors.
 type CkReqFunc func(*testing.T, toclientlib.ReqInf, interface{}, tc.Alerts, error)
diff --git a/traffic_ops/testing/api/v3/about_test.go b/traffic_ops/testing/api/v3/about_test.go
index bcaac2d..d93575d 100644
--- a/traffic_ops/testing/api/v3/about_test.go
+++ b/traffic_ops/testing/api/v3/about_test.go
@@ -16,18 +16,38 @@ package v3
 */
 
 import (
+	"net/http"
 	"testing"
+
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
 )
 
 func TestAbout(t *testing.T) {
-	m, _, err := TOSession.GetAbout()
-	if err != nil {
-		t.Errorf("error from GetAbout(): %v", err)
-	}
-	t.Logf("about: %v", m)
 
-	m, _, err = NoAuthTOSession.GetAbout()
-	if err == nil {
-		t.Error("expected error from GetAbout() when unauthenticated")
+	methodTests := utils.V3TestCase{
+		"GET": {
+			"OK when VALID request": {
+				ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+			},
+			"UNAUTHORIZED when NOT LOGGED IN": {
+				ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+			},
+		},
+	}
+	for method, testCases := range methodTests {
+		t.Run(method, func(t *testing.T) {
+			for name, testCase := range testCases {
+				switch method {
+				case "GET":
+					t.Run(name, func(t *testing.T) {
+						resp, reqInf, err := testCase.ClientSession.GetAbout()
+						for _, check := range testCase.Expectations {
+							check(t, reqInf, resp, tc.Alerts{}, err)
+						}
+					})
+				}
+			}
+		})
 	}
 }
diff --git a/traffic_ops/testing/api/v3/asns_test.go b/traffic_ops/testing/api/v3/asns_test.go
index 2bf9b26..e3587d4 100644
--- a/traffic_ops/testing/api/v3/asns_test.go
+++ b/traffic_ops/testing/api/v3/asns_test.go
@@ -16,6 +16,7 @@ package v3
 */
 
 import (
+	"encoding/json"
 	"net/http"
 	"net/url"
 	"sort"
@@ -25,190 +26,148 @@ import (
 
 	"github.com/apache/trafficcontrol/lib/go-rfc"
 	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/assert"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
+	"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
 )
 
 func TestASN(t *testing.T) {
 	WithObjs(t, []TCObj{Types, CacheGroups, ASN}, func() {
-		GetTestASNsIMS(t)
-		currentTime := time.Now().UTC().Add(-5 * time.Second)
-		time := currentTime.Format(time.RFC1123)
-		var header http.Header
-		header = make(map[string][]string)
-		header.Set(rfc.IfModifiedSince, time)
-		SortTestASNs(t)
-		UpdateTestASNs(t)
-		GetTestASNs(t)
-		GetTestASNsIMSAfterChange(t, header)
-	})
-}
 
-func GetTestASNsIMSAfterChange(t *testing.T, header http.Header) {
-	params := url.Values{}
-	for _, asn := range testData.ASNs {
-		params.Add("asn", strconv.Itoa(asn.ASN))
-		_, reqInf, err := TOSession.GetASNsWithHeader(&params, header)
-		if err != nil {
-			t.Fatalf("Expected no error, but got %v", err.Error())
-		}
-		if reqInf.StatusCode != http.StatusOK {
-			t.Fatalf("Expected 200 status code, got %v", reqInf.StatusCode)
-		}
-		params.Del("asn")
-	}
-	currentTime := time.Now().UTC()
-	currentTime = currentTime.Add(1 * time.Second)
-	timeStr := currentTime.Format(time.RFC1123)
-	header.Set(rfc.IfModifiedSince, timeStr)
-	for _, asn := range testData.ASNs {
-		params.Add("asn", strconv.Itoa(asn.ASN))
-		_, reqInf, err := TOSession.GetASNsWithHeader(&params, header)
-		if err != nil {
-			t.Fatalf("Expected no error, but got %v", err.Error())
-		}
-		if reqInf.StatusCode != http.StatusNotModified {
-			t.Fatalf("Expected 304 status code, got %v", reqInf.StatusCode)
+		tomorrow := time.Now().AddDate(0, 0, 1).Format(time.RFC1123)
+		currentTime := time.Now().UTC().Add(-5 * time.Second)
+		currentTimeRFC := currentTime.Format(time.RFC1123)
+
+		methodTests := utils.V3TestCase{
+			"GET": {
+				"NOT MODIFIED when NO CHANGES made": {
+					ClientSession: TOSession, RequestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+				},
+				"OK when VALID request": {
+					ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), validateSorted()),
+				},
+				"OK when VALID ASN PARAMETER": {
+					ClientSession: TOSession, RequestParams: url.Values{"asn": {"9999"}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1)),
+				},
+			},
+			"PUT": {
+				"OK when VALID request": {
+					ClientSession: TOSession, EndpointId: GetASNId(t, "8888"),
+					RequestBody: map[string]interface{}{
+						"asn":            7777,
+						"cachegroupName": "originCachegroup",
+						"cachegroupId":   -1,
+					},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+				},
+			},
+			"GET AFTER CHANGES": {
+				"OK when CHANGES made": {
+					ClientSession:  TOSession,
+					RequestHeaders: http.Header{rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC}},
+					Expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+				},
+			},
 		}
-		params.Del("asn")
-	}
-}
 
-func GetTestASNsIMS(t *testing.T) {
-	var header http.Header
-	header = make(map[string][]string)
-	params := url.Values{}
-	for _, asn := range testData.ASNs {
-		params.Add("asn", strconv.Itoa(asn.ASN))
-		futureTime := time.Now().AddDate(0, 0, 1)
-		time := futureTime.Format(time.RFC1123)
-		header.Set(rfc.IfModifiedSince, time)
-		_, reqInf, err := TOSession.GetASNsWithHeader(&params, header)
-		if err != nil {
-			t.Fatalf("Expected no error, but got %v", err.Error())
+		for method, testCases := range methodTests {
+			t.Run(method, func(t *testing.T) {
+				for name, testCase := range testCases {
+					asn := tc.ASN{}
+
+					if testCase.RequestBody != nil {
+						if cgId, ok := testCase.RequestBody["cachegroupId"]; ok {
+							if cgId == -1 {
+								if cgName, ok := testCase.RequestBody["cachegroupName"]; ok {
+									testCase.RequestBody["cachegroupId"] = GetCacheGroupId(t, cgName.(string))()
+								}
+							}
+						}
+						dat, err := json.Marshal(testCase.RequestBody)
+						assert.NoError(t, err, "Error occurred when marshalling request body: %v", err)
+						err = json.Unmarshal(dat, &asn)
+						assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+					}
+
+					switch method {
+					case "GET", "GET AFTER CHANGES":
+						t.Run(name, func(t *testing.T) {
+							resp, reqInf, err := testCase.ClientSession.GetASNsWithHeader(&testCase.RequestParams, testCase.RequestHeaders)
+							for _, check := range testCase.Expectations {
+								check(t, reqInf, resp, tc.Alerts{}, err)
+							}
+						})
+					case "PUT":
+						t.Run(name, func(t *testing.T) {
+							alerts, reqInf, err := testCase.ClientSession.UpdateASNByID(testCase.EndpointId(), asn)
+							for _, check := range testCase.Expectations {
+								check(t, reqInf, nil, alerts, err)
+							}
+						})
+					}
+				}
+			})
 		}
-		if reqInf.StatusCode != http.StatusNotModified {
-			t.Fatalf("Expected 304 status code, got %v", reqInf.StatusCode)
-		}
-		params.Del("asn")
-	}
+	})
 }
 
-func CreateTestASNs(t *testing.T) {
-	var header http.Header
-	resp, _, err := TOSession.GetCacheGroupNullableByNameWithHdr(*testData.CacheGroups[0].Name, header)
-	if err != nil {
-		t.Fatalf("unable to get cachgroup ID: %v", err)
-	}
-	for _, asn := range testData.ASNs {
-		asn.CachegroupID = *resp[0].ID
-		resp, _, err := TOSession.CreateASN(asn)
-		t.Log("Response: ", resp)
-		if err != nil {
-			t.Errorf("could not CREATE ASNs: %v", err)
-		}
-	}
-
-}
+func validateSorted() utils.CkReqFunc {
+	return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, alerts tc.Alerts, _ error) {
+		asnResp := resp.([]tc.ASN)
+		var sortedList []string
+		assert.RequireGreaterOrEqual(t, len(asnResp), 2, "Need at least 2 ASNs in Traffic Ops to test sorted, found: %d", len(asnResp))
 
-func SortTestASNs(t *testing.T) {
-	var header http.Header
-	var sortedList []string
-	params := url.Values{}
-	resp, _, err := TOSession.GetASNsWithHeader(&params, header)
-	if err != nil {
-		t.Fatalf("Expected no error, but got %v", err.Error())
-	}
-	for i, _ := range resp {
-		sortedList = append(sortedList, strconv.Itoa(resp[i].ASN))
-	}
+		for _, asn := range asnResp {
+			sortedList = append(sortedList, strconv.Itoa(asn.ASN))
+		}
 
-	res := sort.SliceIsSorted(sortedList, func(p, q int) bool {
-		return sortedList[p] < sortedList[q]
-	})
-	if res != true {
-		t.Errorf("list is not sorted by their names: %v", sortedList)
+		res := sort.SliceIsSorted(sortedList, func(p, q int) bool {
+			return sortedList[p] < sortedList[q]
+		})
+		assert.Equal(t, res, true, "List is not sorted by their names: %v", sortedList)
 	}
 }
 
-func UpdateTestASNs(t *testing.T) {
-	var header http.Header
-	firstASN := testData.ASNs[0]
-	params := url.Values{}
-	params.Add("asn", strconv.Itoa(firstASN.ASN))
-	// Retrieve the ASN by name so we can get the id for the Update
-	resp, _, err := TOSession.GetASNsWithHeader(&params, header)
-	if err != nil {
-		t.Errorf("cannot GET ASN by name: '%v', %v", firstASN.ASN, err)
-	}
-	remoteASN := resp[0]
-	remoteASN.ASN = 7777
-	var alert tc.Alerts
-	alert, _, err = TOSession.UpdateASNByID(remoteASN.ID, remoteASN)
-	if err != nil {
-		t.Errorf("cannot UPDATE ASN by id: %v - %v", err, alert)
-	}
+func GetASNId(t *testing.T, ASN string) func() int {
+	return func() int {
+		params := url.Values{"asn": {ASN}}
 
-	// Retrieve the ASN to check ASN name got updated
-	params.Del("asn")
-	params.Add("id", strconv.Itoa(remoteASN.ID))
-	resp, _, err = TOSession.GetASNsWithHeader(&params, header)
-	if err != nil {
-		t.Errorf("cannot GET ANS by number: '$%v', %v", firstASN.ASN, err)
-	}
-	respASN := resp[0]
-	if respASN.ASN != remoteASN.ASN {
-		t.Errorf("results do not match actual: %v, expected: %v", respASN.ASN, remoteASN.ASN)
-	}
+		resp, _, err := TOSession.GetASNsWithHeader(&params, http.Header{})
+		assert.RequireNoError(t, err, "Get ASNs Request failed with error: %v", err)
+		assert.RequireEqual(t, len(resp), 1, "Expected response object length 1, but got %d", len(resp))
+		assert.RequireNotNil(t, &resp[0].ID, "Expected id to not be nil")
 
-	//Revert back to original ASN number for further functions to work correctly
-	respASN.ASN = firstASN.ASN
-	alert, _, err = TOSession.UpdateASNByID(respASN.ID, respASN)
-	if err != nil {
-		t.Errorf("cannot UPDATE ASN by id: %v - %v", err, alert)
+		return resp[0].ID
 	}
 }
 
-func GetTestASNs(t *testing.T) {
+func CreateTestASNs(t *testing.T) {
+	resp, _, err := TOSession.GetCacheGroupNullableByNameWithHdr(*testData.CacheGroups[0].Name, http.Header{})
+	assert.RequireNoError(t, err, "Unable to get cachgroup ID: %v - resp: %+v", err, resp)
 
-	var header http.Header
-	params := url.Values{}
 	for _, asn := range testData.ASNs {
-		params.Add("asn", strconv.Itoa(asn.ASN))
-		resp, _, err := TOSession.GetASNsWithHeader(&params, header)
-		if err != nil {
-			t.Errorf("cannot GET ASN by name: %v - %v", err, resp)
-		}
-		params.Del("asn")
+		asn.CachegroupID = *resp[0].ID
+		resp, _, err := TOSession.CreateASN(asn)
+		assert.NoError(t, err, "Could not create ASN: %v - resp: %+v", err, resp)
 	}
 }
 
 func DeleteTestASNs(t *testing.T) {
-
 	var header http.Header
 	params := url.Values{}
-	for _, asn := range testData.ASNs {
-		params.Add("asn", strconv.Itoa(asn.ASN))
-		// Retrieve the ASN by name so we can get the id for the Update
-		resp, _, err := TOSession.GetASNsWithHeader(&params, header)
-		if err != nil {
-			t.Errorf("cannot GET ASN by number: %v - %v", asn.ASN, err)
-		}
-		if len(resp) > 0 {
-			respASN := resp[0]
-
-			_, _, err := TOSession.DeleteASNByASN(respASN.ID)
-			if err != nil {
-				t.Errorf("cannot DELETE ASN by ASN number: '%v' %v", respASN.ASN, err)
-			}
-
-			// Retrieve the ASN to see if it got deleted
-			asns, _, err := TOSession.GetASNsWithHeader(&params, header)
-			if err != nil {
-				t.Errorf("error deleting ASN number: %s", err.Error())
-			}
-			if len(asns) > 0 {
-				t.Errorf("expected ASN number: %v to be deleted", asn.ASN)
-			}
-		}
-		params.Del("asn")
+	// Retrieve ASNs to delete
+	resp, _, err := TOSession.GetASNsWithHeader(&params, header)
+	assert.NoError(t, err, "Error trying to fetch ASNs for deletion: %v - resp: %+v", err, resp)
+	for _, asn := range resp {
+		_, _, err := TOSession.DeleteASNByASN(asn.ID)
+		assert.NoError(t, err, "Cannot delete ASN by ASN number: '%v' %v", asn.ASN, err)
+
+		// Retrieve the ASN to see if it got deleted
+		params.Set("asn", strconv.Itoa(asn.ASN))
+		asns, _, err := TOSession.GetASNsWithHeader(&params, header)
+		assert.NoError(t, err, "Error deleting ASN: %s", err)
+		assert.Equal(t, 0, len(asns), "Expected ASN: %v to be deleted", asn.ASN)
 	}
 }
diff --git a/traffic_ops/testing/api/v3/cachegroups_test.go b/traffic_ops/testing/api/v3/cachegroups_test.go
index 73cf5db..b59422f 100644
--- a/traffic_ops/testing/api/v3/cachegroups_test.go
+++ b/traffic_ops/testing/api/v3/cachegroups_test.go
@@ -28,7 +28,6 @@ import (
 	"github.com/apache/trafficcontrol/traffic_ops/testing/api/assert"
 	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
 	"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
-	client "github.com/apache/trafficcontrol/traffic_ops/v3-client"
 )
 
 func TestCacheGroups(t *testing.T) {
@@ -38,59 +37,52 @@ func TestCacheGroups(t *testing.T) {
 		currentTime := time.Now().UTC().Add(-5 * time.Second)
 		currentTimeRFC := currentTime.Format(time.RFC1123)
 
-		methodTests := map[string]map[string]struct {
-			endpointId     func() int
-			clientSession  *client.Session
-			requestParams  url.Values
-			requestHeaders http.Header
-			requestBody    map[string]interface{}
-			expectations   []utils.CkReqFunc
-		}{
+		methodTests := utils.V3TestCase{
 			"GET": {
 				"NOT MODIFIED when NO CHANGES made": {
-					clientSession: TOSession, requestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					ClientSession: TOSession, RequestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"NOT MODIFIED when VALID NAME parameter when NO CHANGES made": {
-					clientSession: TOSession, requestParams: url.Values{"name": {"originCachegroup"}},
-					requestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
-					expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					ClientSession: TOSession, RequestParams: url.Values{"name": {"originCachegroup"}},
+					RequestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
+					Expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"NOT MODIFIED when VALID SHORTNAME parameter when NO CHANGES made": {
-					clientSession: TOSession, requestParams: url.Values{"shortName": {"mog1"}},
-					requestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
-					expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					ClientSession: TOSession, RequestParams: url.Values{"shortName": {"mog1"}},
+					RequestHeaders: http.Header{rfc.IfModifiedSince: {tomorrow}},
+					Expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"OK when VALID request": {
-					clientSession: TOSession, expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"OK when VALID NAME parameter": {
-					clientSession: TOSession, requestParams: url.Values{"name": {"parentCachegroup"}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
+					ClientSession: TOSession, RequestParams: url.Values{"name": {"parentCachegroup"}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
 						ValidateExpectedField("Name", "parentCachegroup")),
 				},
 				"OK when VALID SHORTNAME parameter": {
-					clientSession: TOSession, requestParams: url.Values{"shortName": {"pg2"}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
+					ClientSession: TOSession, RequestParams: url.Values{"shortName": {"pg2"}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
 						ValidateExpectedField("ShortName", "pg2")),
 				},
 				"OK when VALID TOPOLOGY parameter": {
-					clientSession: TOSession, requestParams: url.Values{"topology": {"mso-topology"}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					ClientSession: TOSession, RequestParams: url.Values{"topology": {"mso-topology"}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					clientSession: NoAuthTOSession, expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"POST": {
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					clientSession: NoAuthTOSession, expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"PUT": {
 				"OK when VALID request": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"latitude":            17.5,
 						"longitude":           17.5,
 						"name":                "cachegroup1",
@@ -100,12 +92,12 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":            "EDGE_LOC",
 						"typeId":              -1,
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"PRECONDITION FAILED when updating with IMS & IUS Headers": {
-					endpointId: GetCacheGroupId(t, "parentCachegroup"), clientSession: TOSession,
-					requestHeaders: http.Header{rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC}},
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "parentCachegroup"), ClientSession: TOSession,
+					RequestHeaders: http.Header{rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC}},
+					RequestBody: map[string]interface{}{
 						"latitude":  0,
 						"longitude": 0,
 						"name":      "parentCachegroup",
@@ -113,11 +105,11 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":  "MID_LOC",
 						"typeId":    -1,
 					},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
 				},
 				"PRECONDITION FAILED when updating with IFMATCH ETAG Header": {
-					endpointId: GetCacheGroupId(t, "parentCachegroup2"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "parentCachegroup2"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"latitude":  0,
 						"longitude": 0,
 						"name":      "parentCachegroup2",
@@ -125,25 +117,25 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":  "MID_LOC",
 						"typeId":    -1,
 					},
-					requestHeaders: http.Header{rfc.IfMatch: {rfc.ETag(currentTime)}},
-					expectations:   utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
+					RequestHeaders: http.Header{rfc.IfMatch: {rfc.ETag(currentTime)}},
+					Expectations:   utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
 				},
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: NoAuthTOSession,
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: NoAuthTOSession,
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"DELETE": {
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: NoAuthTOSession,
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: NoAuthTOSession,
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"GET AFTER CHANGES": {
 				"OK when CHANGES made": {
-					clientSession:  TOSession,
-					requestHeaders: http.Header{rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC}},
-					expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					ClientSession:  TOSession,
+					RequestHeaders: http.Header{rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC}},
+					Expectations:   utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 			},
 		}
@@ -153,25 +145,25 @@ func TestCacheGroups(t *testing.T) {
 				for name, testCase := range testCases {
 					cg := tc.CacheGroupNullable{}
 
-					if testCase.requestParams.Has("type") {
-						val := testCase.requestParams.Get("type")
+					if testCase.RequestParams.Has("type") {
+						val := testCase.RequestParams.Get("type")
 						if _, err := strconv.Atoi(val); err != nil {
-							testCase.requestParams.Set("type", strconv.Itoa(GetTypeId(t, val)))
+							testCase.RequestParams.Set("type", strconv.Itoa(GetTypeId(t, val)))
 						}
 					}
 
-					if testCase.requestBody != nil {
-						if _, ok := testCase.requestBody["id"]; ok {
-							testCase.requestBody["id"] = testCase.endpointId()
+					if testCase.RequestBody != nil {
+						if _, ok := testCase.RequestBody["id"]; ok {
+							testCase.RequestBody["id"] = testCase.EndpointId()
 						}
-						if typeId, ok := testCase.requestBody["typeId"]; ok {
+						if typeId, ok := testCase.RequestBody["typeId"]; ok {
 							if typeId == -1 {
-								if typeName, ok := testCase.requestBody["typeName"]; ok {
-									testCase.requestBody["typeId"] = GetTypeId(t, typeName.(string))
+								if typeName, ok := testCase.RequestBody["typeName"]; ok {
+									testCase.RequestBody["typeId"] = GetTypeId(t, typeName.(string))
 								}
 							}
 						}
-						dat, err := json.Marshal(testCase.requestBody)
+						dat, err := json.Marshal(testCase.RequestBody)
 						assert.NoError(t, err, "Error occurred when marshalling request body: %v", err)
 						err = json.Unmarshal(dat, &cg)
 						assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
@@ -180,29 +172,29 @@ func TestCacheGroups(t *testing.T) {
 					switch method {
 					case "GET", "GET AFTER CHANGES":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.GetCacheGroupsByQueryParamsWithHdr(testCase.requestParams, testCase.requestHeaders)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.GetCacheGroupsByQueryParamsWithHdr(testCase.RequestParams, testCase.RequestHeaders)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp, tc.Alerts{}, err)
 							}
 						})
 					case "POST":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.CreateCacheGroupNullable(cg)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.CreateCacheGroupNullable(cg)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp.Response, resp.Alerts, err)
 							}
 						})
 					case "PUT":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.UpdateCacheGroupNullableByIDWithHdr(testCase.endpointId(), cg, testCase.requestHeaders)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.UpdateCacheGroupNullableByIDWithHdr(testCase.EndpointId(), cg, testCase.RequestHeaders)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp.Response, resp.Alerts, err)
 							}
 						})
 					case "DELETE":
 						t.Run(name, func(t *testing.T) {
-							alerts, reqInf, err := testCase.clientSession.DeleteCacheGroupByID(testCase.endpointId())
-							for _, check := range testCase.expectations {
+							alerts, reqInf, err := testCase.ClientSession.DeleteCacheGroupByID(testCase.EndpointId())
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, nil, alerts, err)
 							}
 						})
diff --git a/traffic_ops/testing/api/v4/about_test.go b/traffic_ops/testing/api/v4/about_test.go
index 89584a0..e300ba6 100644
--- a/traffic_ops/testing/api/v4/about_test.go
+++ b/traffic_ops/testing/api/v4/about_test.go
@@ -16,20 +16,38 @@ package v4
 */
 
 import (
+	"net/http"
 	"testing"
 
-	client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
 )
 
 func TestAbout(t *testing.T) {
-	m, _, err := TOSession.GetAbout(client.RequestOptions{})
-	if err != nil {
-		t.Errorf("error from GetAbout(): %v", err)
-	}
-	t.Logf("about: %v", m)
 
-	m, _, err = NoAuthTOSession.GetAbout(client.RequestOptions{})
-	if err == nil {
-		t.Error("expected error from GetAbout() when unauthenticated")
+	methodTests := utils.V4TestCase{
+		"GET": {
+			"OK when VALID request": {
+				ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+			},
+			"UNAUTHORIZED when NOT LOGGED IN": {
+				ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+			},
+		},
+	}
+	for method, testCases := range methodTests {
+		t.Run(method, func(t *testing.T) {
+			for name, testCase := range testCases {
+				switch method {
+				case "GET":
+					t.Run(name, func(t *testing.T) {
+						resp, reqInf, err := testCase.ClientSession.GetAbout(testCase.RequestOpts)
+						for _, check := range testCase.Expectations {
+							check(t, reqInf, resp, tc.Alerts{}, err)
+						}
+					})
+				}
+			}
+		})
 	}
 }
diff --git a/traffic_ops/testing/api/v4/acme_test.go b/traffic_ops/testing/api/v4/acme_test.go
index 25bf014..b37ee53 100644
--- a/traffic_ops/testing/api/v4/acme_test.go
+++ b/traffic_ops/testing/api/v4/acme_test.go
@@ -19,19 +19,31 @@ import (
 	"net/http"
 	"testing"
 
-	client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
 )
 
 func TestAcmeAutoRenew(t *testing.T) {
-	PostTestAutoRenew(t)
-}
 
-func PostTestAutoRenew(t *testing.T) {
-	alerts, reqInf, err := TOSession.AutoRenew(client.RequestOptions{})
-	if err != nil {
-		t.Fatalf("Unexpected error scheduling automatic renewal of ACME certificates: %v - alerts: %+v", err, alerts.Alerts)
+	methodTests := utils.V4TestCase{
+		"POST": {
+			"OK when VALID request": {
+				ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusAccepted)),
+			},
+		},
 	}
-	if reqInf.StatusCode != http.StatusAccepted {
-		t.Fatalf("Expected 202 status code, got %v", reqInf.StatusCode)
+	for method, testCases := range methodTests {
+		t.Run(method, func(t *testing.T) {
+			for name, testCase := range testCases {
+				switch method {
+				case "POST":
+					t.Run(name, func(t *testing.T) {
+						alerts, reqInf, err := testCase.ClientSession.AutoRenew(testCase.RequestOpts)
+						for _, check := range testCase.Expectations {
+							check(t, reqInf, nil, alerts, err)
+						}
+					})
+				}
+			}
+		})
 	}
 }
diff --git a/traffic_ops/testing/api/v4/asns_test.go b/traffic_ops/testing/api/v4/asns_test.go
index f100362..e3f4775 100644
--- a/traffic_ops/testing/api/v4/asns_test.go
+++ b/traffic_ops/testing/api/v4/asns_test.go
@@ -16,6 +16,7 @@ package v4
 */
 
 import (
+	"encoding/json"
 	"net/http"
 	"net/url"
 	"sort"
@@ -24,208 +25,163 @@ import (
 	"time"
 
 	"github.com/apache/trafficcontrol/lib/go-rfc"
+	"github.com/apache/trafficcontrol/lib/go-tc"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/assert"
+	"github.com/apache/trafficcontrol/traffic_ops/testing/api/utils"
+	"github.com/apache/trafficcontrol/traffic_ops/toclientlib"
 	client "github.com/apache/trafficcontrol/traffic_ops/v4-client"
 )
 
 func TestASN(t *testing.T) {
 	WithObjs(t, []TCObj{Types, CacheGroups, ASN}, func() {
-		GetTestASNsIMS(t)
+		tomorrow := time.Now().AddDate(0, 0, 1).Format(time.RFC1123)
 		currentTime := time.Now().UTC().Add(-5 * time.Second)
-		time := currentTime.Format(time.RFC1123)
-		opts := client.NewRequestOptions()
-		opts.Header.Set(rfc.IfModifiedSince, time)
-		SortTestASNs(t)
-		UpdateTestASNs(t)
-		GetTestASNs(t)
-		GetTestASNsIMSAfterChange(t, opts)
+		currentTimeRFC := currentTime.Format(time.RFC1123)
+
+		methodTests := utils.V4TestCase{
+			"GET": {
+				"NOT MODIFIED when NO CHANGES made": {
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfModifiedSince: {tomorrow}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+				},
+				"OK when VALID request": {
+					ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), validateSorted()),
+				},
+				"OK when VALID ASN PARAMETER": {
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"asn": {"9999"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1)),
+				},
+			},
+			"PUT": {
+				"OK when VALID request": {
+					ClientSession: TOSession, EndpointId: GetASNId(t, "8888"),
+					RequestBody: map[string]interface{}{
+						"asn":            7777,
+						"cachegroupName": "originCachegroup",
+						"cachegroupId":   -1,
+					},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+				},
+			},
+			"GET AFTER CHANGES": {
+				"OK when CHANGES made": {
+					ClientSession: TOSession,
+					RequestOpts: client.RequestOptions{
+						Header: http.Header{
+							rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC},
+						},
+					},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+				},
+			},
+		}
+
+		for method, testCases := range methodTests {
+			t.Run(method, func(t *testing.T) {
+				for name, testCase := range testCases {
+					asn := tc.ASN{}
+
+					if testCase.RequestBody != nil {
+						if cgId, ok := testCase.RequestBody["cachegroupId"]; ok {
+							if cgId == -1 {
+								if cgName, ok := testCase.RequestBody["cachegroupName"]; ok {
+									testCase.RequestBody["cachegroupId"] = GetCacheGroupId(t, cgName.(string))()
+								}
+							}
+						}
+						dat, err := json.Marshal(testCase.RequestBody)
+						assert.NoError(t, err, "Error occurred when marshalling request body: %v", err)
+						err = json.Unmarshal(dat, &asn)
+						assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
+					}
+
+					switch method {
+					case "GET", "GET AFTER CHANGES":
+						t.Run(name, func(t *testing.T) {
+							resp, reqInf, err := testCase.ClientSession.GetASNs(testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
+								check(t, reqInf, resp.Response, resp.Alerts, err)
+							}
+						})
+					case "PUT":
+						t.Run(name, func(t *testing.T) {
+							alerts, reqInf, err := testCase.ClientSession.UpdateASN(testCase.EndpointId(), asn, testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
+								check(t, reqInf, nil, alerts, err)
+							}
+						})
+					}
+				}
+			})
+		}
 	})
 }
 
-func GetTestASNsIMSAfterChange(t *testing.T, opts client.RequestOptions) {
-	if opts.QueryParameters == nil {
-		opts.QueryParameters = url.Values{}
-	}
-	for _, asn := range testData.ASNs {
-		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
-		_, reqInf, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("Expected no error, but got %v", err)
-		}
-		if reqInf.StatusCode != http.StatusOK {
-			t.Errorf("Expected 200 status code, got %v", reqInf.StatusCode)
-		}
-	}
-	currentTime := time.Now().UTC()
-	currentTime = currentTime.Add(1 * time.Second)
-	timeStr := currentTime.Format(time.RFC1123)
-	opts.Header.Set(rfc.IfModifiedSince, timeStr)
-	for _, asn := range testData.ASNs {
-		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
-		_, reqInf, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("Expected no error, but got %v", err)
-		}
-		if reqInf.StatusCode != http.StatusNotModified {
-			t.Errorf("Expected 304 status code, got %v", reqInf.StatusCode)
+func validateSorted() utils.CkReqFunc {
+	return func(t *testing.T, _ toclientlib.ReqInf, resp interface{}, alerts tc.Alerts, _ error) {
+		asnResp := resp.([]tc.ASN)
+		var sortedList []string
+		assert.RequireGreaterOrEqual(t, len(asnResp), 2, "Need at least 2 ASNs in Traffic Ops to test sorted, found: %d", len(asnResp))
+
+		for _, asn := range asnResp {
+			sortedList = append(sortedList, strconv.Itoa(asn.ASN))
 		}
+
+		res := sort.SliceIsSorted(sortedList, func(p, q int) bool {
+			return sortedList[p] < sortedList[q]
+		})
+		assert.Equal(t, res, true, "List is not sorted by their names: %v", sortedList)
 	}
 }
 
-func GetTestASNsIMS(t *testing.T) {
-	opts := client.NewRequestOptions()
-	for _, asn := range testData.ASNs {
-		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
-		futureTime := time.Now().AddDate(0, 0, 1)
-		time := futureTime.Format(time.RFC1123)
-		opts.Header.Set(rfc.IfModifiedSince, time)
-		_, reqInf, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("Expected no error, but got %v", err)
-		}
-		if reqInf.StatusCode != http.StatusNotModified {
-			t.Errorf("Expected 304 status code, got %v", reqInf.StatusCode)
-		}
+func GetASNId(t *testing.T, ASN string) func() int {
+	return func() int {
+		opts := client.NewRequestOptions()
+		opts.QueryParameters.Set("asn", ASN)
+
+		resp, _, err := TOSession.GetASNs(opts)
+		assert.RequireNoError(t, err, "Get ASNs Request failed with error: %v", err)
+		assert.RequireEqual(t, len(resp.Response), 1, "Expected response object length 1, but got %d", len(resp.Response))
+		assert.RequireNotNil(t, &resp.Response[0].ID, "Expected id to not be nil")
+
+		return resp.Response[0].ID
 	}
 }
 
 func CreateTestASNs(t *testing.T) {
-	if len(testData.CacheGroups) < 1 {
-		t.Fatal("Need at least one Cache Group to test creating ASNs")
-	}
+	assert.RequireGreaterOrEqual(t, len(testData.CacheGroups), 1, "Need at least one Cache Group to test creating ASNs")
+
 	cg := testData.CacheGroups[0]
-	if cg.Name == nil {
-		t.Fatal("Cache Group found in the test data with null or undefined name")
-	}
+	assert.RequireNotNil(t, cg.Name, "Cache Group found in the test data with null or undefined name")
 
 	opts := client.NewRequestOptions()
 	opts.QueryParameters.Set("name", *cg.Name)
 	resp, _, err := TOSession.GetCacheGroups(opts)
-	if err != nil {
-		t.Fatalf("unable to get cachgroup ID: %v - alerts: %+v", err, resp.Alerts)
-	}
-	if len(resp.Response) != 1 {
-		t.Fatalf("Expected exactly one Cache Group with Name '%s', got: %d", *cg.Name, len(resp.Response))
-	}
-	if resp.Response[0].ID == nil {
-		t.Fatalf("Cache Group '%s' had no ID in Traffic Ops response", *cg.Name)
-	}
+	assert.RequireNoError(t, err, "Unable to get cachgroup ID: %v - alerts: %+v", err, resp.Alerts)
+	assert.RequireEqual(t, 1, len(resp.Response), "Expected exactly one Cache Group with Name '%s', got: %d", *cg.Name, len(resp.Response))
+	assert.RequireNotNil(t, resp.Response[0].ID, "Cache Group '%s' had no ID in Traffic Ops response", *cg.Name)
+
 	id := *resp.Response[0].ID
 	for _, asn := range testData.ASNs {
 		asn.CachegroupID = id
 		resp, _, err := TOSession.CreateASN(asn, client.RequestOptions{})
-		if err != nil {
-			t.Errorf("could not create ASN: %v - alerts: %+v", err, resp)
-		}
-	}
-
-}
-
-func SortTestASNs(t *testing.T) {
-	var sortedList []string
-	resp, _, err := TOSession.GetASNs(client.RequestOptions{})
-	if err != nil {
-		t.Fatalf("Expected no error, but got %v", err.Error())
-	}
-	if len(resp.Response) < 2 {
-		t.Fatal("Cannot test sort order with less than 2 ASNs")
-	}
-	for _, asn := range resp.Response {
-		sortedList = append(sortedList, strconv.Itoa(asn.ASN))
-	}
-
-	res := sort.SliceIsSorted(sortedList, func(p, q int) bool {
-		return sortedList[p] < sortedList[q]
-	})
-	if res != true {
-		t.Errorf("list is not sorted by their names: %v", sortedList)
-	}
-}
-
-func UpdateTestASNs(t *testing.T) {
-	if len(testData.ASNs) < 1 {
-		t.Fatal("Need at least one ASN to test updating ASNs")
-	}
-	firstASN := testData.ASNs[0]
-
-	opts := client.NewRequestOptions()
-	opts.QueryParameters.Set("asn", strconv.Itoa(firstASN.ASN))
-
-	resp, _, err := TOSession.GetASNs(opts)
-	if err != nil {
-		t.Fatalf("cannot get ASN by ASN %d: %v - alerts: %+v", firstASN.ASN, err, resp.Alerts)
-	}
-	if len(resp.Response) < 1 {
-		t.Fatalf("Expected ASN %d to exist, but Traffic Ops returned no such ASN", firstASN.ASN)
-	}
-
-	remoteASN := resp.Response[0]
-	remoteASN.ASN = 7777
-	alert, _, err := TOSession.UpdateASN(remoteASN.ID, remoteASN, client.RequestOptions{})
-	if err != nil {
-		t.Fatalf("cannot update ASN by id: %v - alerts: %+v", err, alert)
-	}
-
-	opts.QueryParameters.Del("asn")
-	opts.QueryParameters.Set("id", strconv.Itoa(remoteASN.ID))
-	resp, _, err = TOSession.GetASNs(opts)
-	if err != nil {
-		t.Errorf("cannot get ANS by ID %d: %v - alerts: %+v", firstASN.ASN, err, resp.Alerts)
-	}
-	if len(resp.Response) < 1 {
-		t.Fatalf("Expected ASN with ID %d to exist after update, but Traffic Ops returned no such ASN", remoteASN.ID)
-	}
-	respASN := resp.Response[0]
-	if respASN.ASN != remoteASN.ASN {
-		t.Errorf("results do not match actual: %v, expected: %v", respASN.ASN, remoteASN.ASN)
-	}
-
-	//Revert back to original ASN number for further functions to work correctly
-	respASN.ASN = firstASN.ASN
-	alert, _, err = TOSession.UpdateASN(respASN.ID, respASN, client.RequestOptions{})
-	if err != nil {
-		t.Errorf("cannot update ASN by id: %v - alerts: %+v", err, alert)
-	}
-}
-
-func GetTestASNs(t *testing.T) {
-	opts := client.NewRequestOptions()
-	for _, asn := range testData.ASNs {
-		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
-		resp, _, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("cannot get ASN by asn: %v - alerts: %+v", err, resp.Alerts)
-		}
+		assert.NoError(t, err, "Could not create ASN: %v - alerts: %+v", err, resp)
 	}
 }
 
 func DeleteTestASNs(t *testing.T) {
 	opts := client.NewRequestOptions()
-	for _, asn := range testData.ASNs {
-		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
-		resp, _, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("cannot get ASN %d: %v - alerts: %+v", asn.ASN, err, resp.Alerts)
-			continue
-		}
-		if len(resp.Response) < 1 {
-			t.Errorf("ASN %d existed in the test data, but not in Traffic Ops", asn.ASN)
-			continue
-		}
-
-		respASN := resp.Response[0]
-
-		alerts, _, err := TOSession.DeleteASN(respASN.ID, client.RequestOptions{})
-		if err != nil {
-			t.Errorf("cannot delete ASN %d: %v - alerts: %+v", respASN.ASN, err, alerts)
-		}
+	// Retrieve the ASNs to delete
+	asns, _, err := TOSession.GetASNs(opts)
+	assert.NoError(t, err, "Error trying to fetch ASNs for deletion: %v - alerts: %+v", err, asns.Alerts)
+	for _, asn := range asns.Response {
+		alerts, _, err := TOSession.DeleteASN(asn.ID, client.RequestOptions{})
+		assert.NoError(t, err, "Cannot delete ASN %d: %v - alerts: %+v", asn.ASN, err, alerts)
 
 		// Retrieve the ASN to see if it got deleted
+		opts.QueryParameters.Set("asn", strconv.Itoa(asn.ASN))
 		asns, _, err := TOSession.GetASNs(opts)
-		if err != nil {
-			t.Errorf("error trying to fetch ASN after deletion: %v - alerts: %+v", err, asns.Alerts)
-		}
-		if len(asns.Response) > 0 {
-			t.Errorf("expected ASN %d to be deleted, but it was found in Traffic Ops's response", asn.ASN)
-		}
+		assert.NoError(t, err, "Error trying to fetch ASN after deletion: %v - alerts: %+v", err, asns.Alerts)
+		assert.Equal(t, 0, len(asns.Response), "Expected ASN %d to be deleted, but it was found in Traffic Ops's response", asn.ASN)
 	}
 }
diff --git a/traffic_ops/testing/api/v4/cachegroups_test.go b/traffic_ops/testing/api/v4/cachegroups_test.go
index 005d6c3..ea99bc5 100644
--- a/traffic_ops/testing/api/v4/cachegroups_test.go
+++ b/traffic_ops/testing/api/v4/cachegroups_test.go
@@ -39,105 +39,99 @@ func TestCacheGroups(t *testing.T) {
 		currentTime := time.Now().UTC().Add(-5 * time.Second)
 		currentTimeRFC := currentTime.Format(time.RFC1123)
 
-		methodTests := map[string]map[string]struct {
-			endpointId    func() int
-			clientSession *client.Session
-			requestOpts   client.RequestOptions
-			requestBody   map[string]interface{}
-			expectations  []utils.CkReqFunc
-		}{
+		methodTests := utils.V4TestCase{
 			"GET": {
 				"OK when VALID NAME parameter AND Lat/Long are 0": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"name": {"nullLatLongCG"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1), ValidateResponseFields()),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"name": {"nullLatLongCG"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1), ValidateResponseFields()),
 				},
 				"NOT MODIFIED when NO CHANGES made": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{Header: http.Header{rfc.IfModifiedSince: {tomorrow}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{Header: http.Header{rfc.IfModifiedSince: {tomorrow}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"NOT MODIFIED when VALID NAME parameter when NO CHANGES made": {
-					clientSession: TOSession,
-					requestOpts: client.RequestOptions{
+					ClientSession: TOSession,
+					RequestOpts: client.RequestOptions{
 						Header:          http.Header{rfc.IfModifiedSince: {tomorrow}},
 						QueryParameters: url.Values{"name": {"originCachegroup"}},
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"NOT MODIFIED when VALID SHORTNAME parameter when NO CHANGES made": {
-					clientSession: TOSession,
-					requestOpts: client.RequestOptions{
+					ClientSession: TOSession,
+					RequestOpts: client.RequestOptions{
 						Header:          http.Header{rfc.IfModifiedSince: {tomorrow}},
 						QueryParameters: url.Values{"shortName": {"mog1"}},
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusNotModified)),
 				},
 				"OK when VALID request": {
-					clientSession: TOSession, expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					ClientSession: TOSession, Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"OK when VALID NAME parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"name": {"parentCachegroup"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"name": {"parentCachegroup"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
 						ValidateExpectedField("Name", "parentCachegroup")),
 				},
 				"OK when VALID SHORTNAME parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"shortName": {"pg2"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"shortName": {"pg2"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(1),
 						ValidateExpectedField("ShortName", "pg2")),
 				},
 				"OK when VALID TOPOLOGY parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"topology": {"mso-topology"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"topology": {"mso-topology"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"OK when VALID TYPE parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"type": {"ORG_LOC"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseLengthGreaterOrEqual(1),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"type": {"ORG_LOC"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseLengthGreaterOrEqual(1),
 						ValidateExpectedField("TypeName", "ORG_LOC")),
 				},
 				"EMPTY RESPONSE when INVALID ID parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"id": {"10000"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(0)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"id": {"10000"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(0)),
 				},
 				"EMPTY RESPONSE when INVALID TYPE parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"type": {"10000"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(0)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"type": {"10000"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), utils.ResponseHasLength(0)),
 				},
 				"FIRST RESULT when LIMIT=1": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("limit")),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("limit")),
 				},
 				"SECOND RESULT when LIMIT=1 OFFSET=1": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}, "offset": {"1"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("offset")),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}, "offset": {"1"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("offset")),
 				},
 				"SECOND RESULT when LIMIT=1 PAGE=2": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}, "page": {"2"}}},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("page")),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"orderby": {"id"}, "limit": {"1"}, "page": {"2"}}},
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK), ValidatePagination("page")),
 				},
 				"BAD REQUEST when INVALID LIMIT parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"-2"}}},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"-2"}}},
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
 				},
 				"BAD REQUEST when INVALID OFFSET parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"1"}, "offset": {"0"}}},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"1"}, "offset": {"0"}}},
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
 				},
 				"BAD REQUEST when INVALID PAGE parameter": {
-					clientSession: TOSession, requestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"1"}, "page": {"0"}}},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
+					ClientSession: TOSession, RequestOpts: client.RequestOptions{QueryParameters: url.Values{"limit": {"1"}, "page": {"0"}}},
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
 				},
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					clientSession: NoAuthTOSession, expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"POST": {
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					clientSession: NoAuthTOSession, expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					ClientSession: NoAuthTOSession, Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"PUT": {
 				"OK when VALID request": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"latitude":            17.5,
 						"longitude":           17.5,
 						"name":                "cachegroup1",
@@ -147,22 +141,22 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":            "EDGE_LOC",
 						"typeId":              -1,
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"OK when updating CG with null Lat/Long": {
-					endpointId: GetCacheGroupId(t, "nullLatLongCG"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "nullLatLongCG"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"name":      "nullLatLongCG",
 						"shortName": "null-ll",
 						"typeName":  "EDGE_LOC",
 						"fallbacks": []string{"fallback1"},
 						"typeId":    -1,
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 				"BAD REQUEST when updating TYPE of CG in TOPOLOGY": {
-					endpointId: GetCacheGroupId(t, "topology-edge-cg-01"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "topology-edge-cg-01"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"id":        -1,
 						"latitude":  0,
 						"longitude": 0,
@@ -171,16 +165,16 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":  "MID_LOC",
 						"typeId":    -1,
 					},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusBadRequest)),
 				},
 				"PRECONDITION FAILED when updating with IMS & IUS Headers": {
-					endpointId: GetCacheGroupId(t, "parentCachegroup"), clientSession: TOSession,
-					requestOpts: client.RequestOptions{
+					EndpointId: GetCacheGroupId(t, "parentCachegroup"), ClientSession: TOSession,
+					RequestOpts: client.RequestOptions{
 						Header: http.Header{
 							rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC},
 						},
 					},
-					requestBody: map[string]interface{}{
+					RequestBody: map[string]interface{}{
 						"latitude":  0,
 						"longitude": 0,
 						"name":      "parentCachegroup",
@@ -188,11 +182,11 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":  "MID_LOC",
 						"typeId":    -1,
 					},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
 				},
 				"PRECONDITION FAILED when updating with IFMATCH ETAG Header": {
-					endpointId: GetCacheGroupId(t, "parentCachegroup2"), clientSession: TOSession,
-					requestBody: map[string]interface{}{
+					EndpointId: GetCacheGroupId(t, "parentCachegroup2"), ClientSession: TOSession,
+					RequestBody: map[string]interface{}{
 						"latitude":  0,
 						"longitude": 0,
 						"name":      "parentCachegroup2",
@@ -200,33 +194,33 @@ func TestCacheGroups(t *testing.T) {
 						"typeName":  "MID_LOC",
 						"typeId":    -1,
 					},
-					requestOpts:  client.RequestOptions{Header: http.Header{rfc.IfMatch: {rfc.ETag(currentTime)}}},
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
+					RequestOpts:  client.RequestOptions{Header: http.Header{rfc.IfMatch: {rfc.ETag(currentTime)}}},
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusPreconditionFailed)),
 				},
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: NoAuthTOSession,
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: NoAuthTOSession,
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"DELETE": {
 				"NOT FOUND when INVALID ID parameter": {
-					endpointId: func() int { return 111111 }, clientSession: TOSession,
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
+					EndpointId: func() int { return 111111 }, ClientSession: TOSession,
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusNotFound)),
 				},
 				"UNAUTHORIZED when NOT LOGGED IN": {
-					endpointId: GetCacheGroupId(t, "cachegroup1"), clientSession: NoAuthTOSession,
-					expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
+					EndpointId: GetCacheGroupId(t, "cachegroup1"), ClientSession: NoAuthTOSession,
+					Expectations: utils.CkRequest(utils.HasError(), utils.HasStatus(http.StatusUnauthorized)),
 				},
 			},
 			"GET AFTER CHANGES": {
 				"OK when CHANGES made": {
-					clientSession: TOSession,
-					requestOpts: client.RequestOptions{
+					ClientSession: TOSession,
+					RequestOpts: client.RequestOptions{
 						Header: http.Header{
 							rfc.IfModifiedSince: {currentTimeRFC}, rfc.IfUnmodifiedSince: {currentTimeRFC},
 						},
 					},
-					expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
+					Expectations: utils.CkRequest(utils.NoError(), utils.HasStatus(http.StatusOK)),
 				},
 			},
 			"CDNLOCK": {
@@ -239,25 +233,25 @@ func TestCacheGroups(t *testing.T) {
 				for name, testCase := range testCases {
 					cg := tc.CacheGroupNullable{}
 
-					if testCase.requestOpts.QueryParameters.Has("type") {
-						val := testCase.requestOpts.QueryParameters.Get("type")
+					if testCase.RequestOpts.QueryParameters.Has("type") {
+						val := testCase.RequestOpts.QueryParameters.Get("type")
 						if _, err := strconv.Atoi(val); err != nil {
-							testCase.requestOpts.QueryParameters.Set("type", strconv.Itoa(GetTypeId(t, val)))
+							testCase.RequestOpts.QueryParameters.Set("type", strconv.Itoa(GetTypeId(t, val)))
 						}
 					}
 
-					if testCase.requestBody != nil {
-						if _, ok := testCase.requestBody["id"]; ok {
-							testCase.requestBody["id"] = testCase.endpointId()
+					if testCase.RequestBody != nil {
+						if _, ok := testCase.RequestBody["id"]; ok {
+							testCase.RequestBody["id"] = testCase.EndpointId()
 						}
-						if typeId, ok := testCase.requestBody["typeId"]; ok {
+						if typeId, ok := testCase.RequestBody["typeId"]; ok {
 							if typeId == -1 {
-								if typeName, ok := testCase.requestBody["typeName"]; ok {
-									testCase.requestBody["typeId"] = GetTypeId(t, typeName.(string))
+								if typeName, ok := testCase.RequestBody["typeName"]; ok {
+									testCase.RequestBody["typeId"] = GetTypeId(t, typeName.(string))
 								}
 							}
 						}
-						dat, err := json.Marshal(testCase.requestBody)
+						dat, err := json.Marshal(testCase.RequestBody)
 						assert.NoError(t, err, "Error occurred when marshalling request body: %v", err)
 						err = json.Unmarshal(dat, &cg)
 						assert.NoError(t, err, "Error occurred when unmarshalling request body: %v", err)
@@ -266,29 +260,29 @@ func TestCacheGroups(t *testing.T) {
 					switch method {
 					case "GET", "GET AFTER CHANGES":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.GetCacheGroups(testCase.requestOpts)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.GetCacheGroups(testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp.Response, resp.Alerts, err)
 							}
 						})
 					case "POST":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.CreateCacheGroup(cg, testCase.requestOpts)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.CreateCacheGroup(cg, testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp.Response, resp.Alerts, err)
 							}
 						})
 					case "PUT":
 						t.Run(name, func(t *testing.T) {
-							resp, reqInf, err := testCase.clientSession.UpdateCacheGroup(testCase.endpointId(), cg, testCase.requestOpts)
-							for _, check := range testCase.expectations {
+							resp, reqInf, err := testCase.ClientSession.UpdateCacheGroup(testCase.EndpointId(), cg, testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, resp.Response, resp.Alerts, err)
 							}
 						})
 					case "DELETE":
 						t.Run(name, func(t *testing.T) {
-							alerts, reqInf, err := testCase.clientSession.DeleteCacheGroup(testCase.endpointId(), testCase.requestOpts)
-							for _, check := range testCase.expectations {
+							alerts, reqInf, err := testCase.ClientSession.DeleteCacheGroup(testCase.EndpointId(), testCase.RequestOpts)
+							for _, check := range testCase.Expectations {
 								check(t, reqInf, nil, alerts, err)
 							}
 						})