func catch(thread *skylark.Thread, _ *skylark.Builtin, args skylark.Tuple, kwargs []skylark.Tuple) (skylark.Value, error) {
	var fn skylark.Callable
	if err := skylark.UnpackArgs("catch", args, kwargs, "fn", &fn); err != nil {
		return nil, err
	}
	if _, err := skylark.Call(thread, fn, nil, nil); err != nil {
		return skylark.String(err.Error()), nil
	}
	return skylark.None, nil
}
catch(f) evaluates f() and returns its evaluation error message
if it failed or None if it succeeded.
package skylarktest
import (
	"bytes"
	"fmt"
	"go/build"
	"path/filepath"
	"regexp"
	"sync"
	"github.com/google/skylark"
	"github.com/google/skylark/skylarkstruct"
)
const localKey = "Reporter"
type Reporter interface {
	Error(args ...interface{})
}
func SetReporter(thread *skylark.Thread, r Reporter) {
	thread.SetLocal(localKey, r)
}
func GetReporter(thread *skylark.Thread) Reporter {
	r, ok := thread.Local(localKey).(Reporter)
	if !ok {
		panic("internal error: skylarktest.SetReporter was not called")
	}
	return r
}
var (
	once      sync.Once
	assert    skylark.StringDict
	assertErr error
)
func LoadAssertModule() (skylark.StringDict, error) {
	once.Do(func() {
		predeclared := skylark.StringDict{
			"error":   skylark.NewBuiltin("error", error_),
			"catch":   skylark.NewBuiltin("catch", catch),
			"matches": skylark.NewBuiltin("matches", matches),
			"struct":  skylark.NewBuiltin("struct", skylarkstruct.Make),
			"_freeze": skylark.NewBuiltin("freeze", freeze),
		}
		filename := DataFile("skylark/skylarktest", "assert.sky")
		thread := new(skylark.Thread)
		assert, assertErr = skylark.ExecFile(thread, filename, nil, predeclared)
	})
	return assert, assertErr
}