예제 #1
0
func registerTestSuite(
	makeDeps func(context.Context) BucketTestDeps,
	prototype bucketTestSetUpInterface) {
	suitePointerType := reflect.TypeOf(prototype)
	suiteType := suitePointerType.Elem()

	// We don't need anything fancy at the suite level.
	var ts ogletest.TestSuite
	ts.Name = getSuiteName(suiteType)

	// For each method, we create a test function.
	for _, method := range getTestMethods(suitePointerType) {
		var tf ogletest.TestFunction
		tf.Name = method.Name

		// Create an instance to be shared among SetUp and the test function itself.
		var instance reflect.Value = reflect.New(suiteType)

		// SetUp should create a bucket and then initialize the suite object,
		// remembering that the suite implements bucketTestSetUpInterface.
		var report reqtrace.ReportFunc
		tf.SetUp = func(*ogletest.TestInfo) {
			// Start tracing.
			var testCtx context.Context
			testCtx, report = reqtrace.Trace(context.Background(), "Overall test")

			// Set up the bucket and other dependencies.
			makeDepsCtx, makeDepsReport := reqtrace.StartSpan(testCtx, "Test setup")
			deps := makeDeps(makeDepsCtx)
			makeDepsReport(nil)

			// Hand off the dependencies and the context to the test.
			deps.ctx = testCtx
			instance.Interface().(bucketTestSetUpInterface).setUpBucketTest(deps)
		}

		// The test function itself should simply invoke the method.
		methodCopy := method
		tf.Run = func() {
			methodCopy.Func.Call([]reflect.Value{instance})
		}

		// Report the test result.
		tf.TearDown = func() {
			report(errors.New(
				"TODO(jacobsa): Plumb through the test failure status. " +
					"Or offer tracing in ogletest itself."))
		}

		// Save the test function.
		ts.TestFunctions = append(ts.TestFunctions, tf)
	}

	// Register the suite.
	ogletest.Register(ts)
}
예제 #2
0
// Run a single test function, returning a slice of failure records.
func runTestFunction(tf TestFunction) (failures []FailureRecord) {
	// Set up a clean slate for this test. Make sure to reset it after everything
	// below is finished, so we don't accidentally use it elsewhere.
	currentlyRunningTest = newTestInfo()
	defer func() {
		currentlyRunningTest = nil
	}()

	ti := currentlyRunningTest

	// Start a trace.
	var reportOutcome reqtrace.ReportFunc
	ti.Ctx, reportOutcome = reqtrace.Trace(ti.Ctx, tf.Name)

	// Run the SetUp function, if any, paying attention to whether it panics.
	setUpPanicked := false
	if tf.SetUp != nil {
		setUpPanicked = runWithProtection(func() { tf.SetUp(ti) })
	}

	// Run the test function itself, but only if the SetUp function didn't panic.
	// (This includes AssertThat errors.)
	if !setUpPanicked {
		runWithProtection(tf.Run)
	}

	// Run the TearDown function, if any.
	if tf.TearDown != nil {
		runWithProtection(tf.TearDown)
	}

	// Tell the mock controller for the tests to report any errors it's sitting
	// on.
	ti.MockController.Finish()

	// Report the outcome to reqtrace.
	if len(ti.failureRecords) == 0 {
		reportOutcome(nil)
	} else {
		reportOutcome(fmt.Errorf("%v failure records", len(ti.failureRecords)))
	}

	return ti.failureRecords
}