test/modules/shell.go: have a single NewShell call with functional expect.Session support.
MultiPart: 1/5

Change-Id: Iba39c53991f9528c619e63431106f42a35e58ebf
diff --git a/cmd/servicerunner/main.go b/cmd/servicerunner/main.go
index fa7a33a..a9ab523 100644
--- a/cmd/servicerunner/main.go
+++ b/cmd/servicerunner/main.go
@@ -66,7 +66,7 @@
 
 	vars := map[string]string{}
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, false, nil)
 	if err != nil {
 		panic(fmt.Sprintf("modules.NewShell: %s", err))
 	}
diff --git a/examples/rps/rpsbot/impl_test.go b/examples/rps/rpsbot/impl_test.go
index e7b3b49..a662320 100644
--- a/examples/rps/rpsbot/impl_test.go
+++ b/examples/rps/rpsbot/impl_test.go
@@ -59,7 +59,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("Could not create shell: %v", err)
 	}
diff --git a/lib/signals/signals_test.go b/lib/signals/signals_test.go
index 293f7c3..6445c03 100644
--- a/lib/signals/signals_test.go
+++ b/lib/signals/signals_test.go
@@ -9,7 +9,6 @@
 	"runtime"
 	"syscall"
 	"testing"
-	"time"
 
 	"v.io/v23"
 	"v.io/v23/context"
@@ -23,7 +22,6 @@
 	vflag "v.io/x/ref/security/flag"
 	"v.io/x/ref/services/mgmt/device"
 	"v.io/x/ref/test"
-	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 )
 
@@ -101,8 +99,8 @@
 	}
 }
 
-func newShell(t *testing.T, ctx *context.T, command string) (*modules.Shell, modules.Handle, *expect.Session) {
-	sh, err := modules.NewShell(ctx, nil)
+func newShell(t *testing.T, ctx *context.T, command string) (*modules.Shell, modules.Handle) {
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -110,10 +108,9 @@
 	if err != nil {
 		sh.Cleanup(os.Stderr, os.Stderr)
 		t.Fatalf("unexpected error: %s", err)
-		return nil, nil, nil
+		return nil, nil
 	}
-	session := expect.NewSession(t, handle.Stdout(), time.Minute)
-	return sh, handle, session
+	return sh, handle
 }
 
 // TestCleanShutdownSignal verifies that sending a signal to a child that
@@ -122,14 +119,14 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	checkSignalIsDefault(t, syscall.SIGINT)
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.Expectf("received signal %s", syscall.SIGINT)
+	h.Expectf("received signal %s", syscall.SIGINT)
 	fmt.Fprintf(h.Stdin(), "close\n")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestCleanShutdownStop verifies that sending a stop comamnd to a child that
@@ -138,13 +135,13 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	s.Expectf("received signal %s", v23.LocalStop)
+	h.Expectf("received signal %s", v23.LocalStop)
 	fmt.Fprintf(h.Stdin(), "close\n")
-	s.ExpectEOF()
+	h.ExpectEOF()
 
 }
 
@@ -155,17 +152,17 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleCustomWithStop")
+	sh, h := newShell(t, ctx, "handleCustomWithStop")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	s.Expectf("received signal %s", v23.LocalStop)
+	h.Expectf("received signal %s", v23.LocalStop)
 	fmt.Fprintf(h.Stdin(), "close\n")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
-func testExitStatus(t *testing.T, h modules.Handle, s *expect.Session, code int) {
-	s.ExpectEOF()
+func testExitStatus(t *testing.T, h modules.Handle, code int) {
+	h.ExpectEOF()
 	_, file, line, _ := runtime.Caller(1)
 	file = filepath.Base(file)
 	if got, want := h.Shutdown(os.Stdout, os.Stderr), fmt.Errorf("exit status %d", code); got.Error() != want.Error() {
@@ -179,11 +176,11 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleCustom")
+	sh, h := newShell(t, ctx, "handleCustom")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	testExitStatus(t, h, s, v23.UnhandledStopExitCode)
+	testExitStatus(t, h, v23.UnhandledStopExitCode)
 }
 
 // TestDoubleSignal verifies that sending a succession of two signals to a child
@@ -193,15 +190,15 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	checkSignalIsDefault(t, syscall.SIGTERM)
 	syscall.Kill(h.Pid(), syscall.SIGTERM)
-	s.Expectf("received signal %s", syscall.SIGTERM)
+	h.Expectf("received signal %s", syscall.SIGTERM)
 	checkSignalIsDefault(t, syscall.SIGINT)
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	testExitStatus(t, h, s, DoubleStopExitCode)
+	testExitStatus(t, h, DoubleStopExitCode)
 }
 
 // TestSignalAndStop verifies that sending a signal followed by a stop command
@@ -211,14 +208,14 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	checkSignalIsDefault(t, syscall.SIGTERM)
 	syscall.Kill(h.Pid(), syscall.SIGTERM)
-	s.Expectf("received signal %s", syscall.SIGTERM)
+	h.Expectf("received signal %s", syscall.SIGTERM)
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	testExitStatus(t, h, s, DoubleStopExitCode)
+	testExitStatus(t, h, DoubleStopExitCode)
 }
 
 // TestDoubleStop verifies that sending a succession of stop commands to a child
@@ -228,13 +225,13 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	s.Expectf("received signal %s", v23.LocalStop)
+	h.Expectf("received signal %s", v23.LocalStop)
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	testExitStatus(t, h, s, DoubleStopExitCode)
+	testExitStatus(t, h, DoubleStopExitCode)
 }
 
 // TestSendUnhandledSignal verifies that sending a signal that the child does
@@ -243,12 +240,12 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaults")
+	sh, h := newShell(t, ctx, "handleDefaults")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	checkSignalIsNotDefault(t, syscall.SIGABRT)
 	syscall.Kill(h.Pid(), syscall.SIGABRT)
-	testExitStatus(t, h, s, 2)
+	testExitStatus(t, h, 2)
 }
 
 // TestDoubleSignalIgnoreChan verifies that, even if we ignore the channel that
@@ -259,16 +256,16 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleDefaultsIgnoreChan")
+	sh, h := newShell(t, ctx, "handleDefaultsIgnoreChan")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	// Even if we ignore the channel that ShutdownOnSignals returns,
 	// sending two signals should still cause the process to exit.
 	checkSignalIsDefault(t, syscall.SIGTERM)
 	syscall.Kill(h.Pid(), syscall.SIGTERM)
 	checkSignalIsDefault(t, syscall.SIGINT)
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	testExitStatus(t, h, s, DoubleStopExitCode)
+	testExitStatus(t, h, DoubleStopExitCode)
 }
 
 // TestHandlerCustomSignal verifies that sending a non-default signal to a
@@ -277,14 +274,14 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, h, s := newShell(t, ctx, "handleCustom")
+	sh, h := newShell(t, ctx, "handleCustom")
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	s.Expect("ready")
+	h.Expect("ready")
 	checkSignalIsNotDefault(t, syscall.SIGABRT)
 	syscall.Kill(h.Pid(), syscall.SIGABRT)
-	s.Expectf("received signal %s", syscall.SIGABRT)
+	h.Expectf("received signal %s", syscall.SIGABRT)
 	fmt.Fprintf(h.Stdin(), "stop\n")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestHandlerCustomSignalWithStop verifies that sending a custom stop signal
@@ -296,13 +293,13 @@
 
 	for _, signal := range []syscall.Signal{syscall.SIGABRT, syscall.SIGHUP} {
 		ctx, _ := vtrace.SetNewTrace(rootCtx)
-		sh, h, s := newShell(t, ctx, "handleCustomWithStop")
-		s.Expect("ready")
+		sh, h := newShell(t, ctx, "handleCustomWithStop")
+		h.Expect("ready")
 		checkSignalIsNotDefault(t, signal)
 		syscall.Kill(h.Pid(), signal)
-		s.Expectf("received signal %s", signal)
+		h.Expectf("received signal %s", signal)
 		fmt.Fprintf(h.Stdin(), "close\n")
-		s.ExpectEOF()
+		h.ExpectEOF()
 		sh.Cleanup(os.Stderr, os.Stderr)
 	}
 }
@@ -355,7 +352,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -370,9 +367,8 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
 	appCycleName := <-ch
-	s.Expect("ready")
+	h.Expect("ready")
 	appCycle := appcycle.AppCycleClient(appCycleName)
 	stream, err := appCycle.Stop(ctx)
 	if err != nil {
@@ -385,7 +381,7 @@
 	if err := stream.Finish(); err != nil {
 		t.Fatalf("Got error: %v", err)
 	}
-	s.Expectf("received signal %s", v23.RemoteStop)
+	h.Expectf("received signal %s", v23.RemoteStop)
 	fmt.Fprintf(h.Stdin(), "close\n")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
diff --git a/profiles/internal/ipc/resolve_test.go b/profiles/internal/ipc/resolve_test.go
index ae33d34..ce35790 100644
--- a/profiles/internal/ipc/resolve_test.go
+++ b/profiles/internal/ipc/resolve_test.go
@@ -67,7 +67,7 @@
 }
 
 func TestResolveToEndpoint(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("modules.NewShell failed: %s", err)
 	}
diff --git a/profiles/internal/ipc/stream/manager/manager_test.go b/profiles/internal/ipc/stream/manager/manager_test.go
index bf6e893..bcebc33 100644
--- a/profiles/internal/ipc/stream/manager/manager_test.go
+++ b/profiles/internal/ipc/stream/manager/manager_test.go
@@ -531,7 +531,7 @@
 
 func testServerRestartDuringClientLifetime(t *testing.T, protocol string) {
 	client := InternalNew(naming.FixedRoutingID(0xcccccccc))
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -561,9 +561,8 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	s = expect.NewSession(t, h.Stdout(), time.Minute)
 	// Restarting the server, listening on the same address as before
-	if addr2 := s.ReadLine(); addr2 != addr || err != nil {
+	if addr2 := h.ReadLine(); addr2 != addr || err != nil {
 		t.Fatalf("Got (%q, %v) want (%q, nil)", addr2, err, addr)
 	}
 	if _, err := client.Dial(ep); err != nil {
diff --git a/profiles/internal/ipc/test/client_test.go b/profiles/internal/ipc/test/client_test.go
index 30fd356..1bcabf0 100644
--- a/profiles/internal/ipc/test/client_test.go
+++ b/profiles/internal/ipc/test/client_test.go
@@ -10,8 +10,6 @@
 	"testing"
 	"time"
 
-	"v.io/x/lib/vlog"
-
 	"v.io/v23"
 	"v.io/v23/context"
 	"v.io/v23/ipc"
@@ -38,7 +36,7 @@
 }
 
 func runMountTable(t *testing.T, ctx *context.T) (*modules.Shell, func()) {
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -48,25 +46,17 @@
 	}
 	sh.Forget(root)
 
-	rootSession := expect.NewSession(t, root.Stdout(), time.Minute)
-	rootSession.ExpectVar("PID")
-	rootName := rootSession.ExpectVar("MT_NAME")
+	root.ExpectVar("PID")
+	rootName := root.ExpectVar("MT_NAME")
 
 	deferFn := func() {
-		if testing.Verbose() {
-			vlog.Infof("------ shell cleanup ------")
-			sh.Cleanup(os.Stderr, os.Stderr)
-			vlog.Infof("------ root shutdown ------")
-			root.Shutdown(os.Stderr, os.Stderr)
-		} else {
-			sh.Cleanup(nil, nil)
-			root.Shutdown(nil, nil)
-		}
+		sh.Cleanup(os.Stderr, os.Stderr)
+		root.Shutdown(os.Stderr, os.Stderr)
 	}
 
 	if t.Failed() {
 		deferFn()
-		t.Fatalf("%s", rootSession.Error())
+		t.Fatalf("%s", root.Error())
 	}
 	sh.SetVar(consts.NamespaceRootPrefix, rootName)
 	if err = v23.GetNamespace(ctx).SetRoots(rootName); err != nil {
@@ -463,7 +453,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx))
+	sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -472,9 +462,8 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	session := expect.NewSession(t, server.Stdout(), time.Minute)
-	session.ReadLine()
-	serverName := session.ExpectVar("NAME")
+	server.ReadLine()
+	serverName := server.ExpectVar("NAME")
 	serverEP, _ := naming.SplitAddressName(serverName)
 	ep, _ := inaming.NewEndpoint(serverEP)
 
@@ -511,7 +500,6 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	session = expect.NewSession(t, server.Stdout(), time.Minute)
 	defer server.Shutdown(os.Stderr, os.Stderr)
 	expected = "mymessage again: bratman\n"
 	if result, err := makeCall(ctx); err != nil || result != expected {
diff --git a/profiles/internal/ipc/test/proxy_test.go b/profiles/internal/ipc/test/proxy_test.go
index 0744417..eb035a1 100644
--- a/profiles/internal/ipc/test/proxy_test.go
+++ b/profiles/internal/ipc/test/proxy_test.go
@@ -30,7 +30,6 @@
 	inaming "v.io/x/ref/profiles/internal/naming"
 	tnaming "v.io/x/ref/profiles/internal/testing/mocks/naming"
 	ivtrace "v.io/x/ref/profiles/internal/vtrace"
-	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 	tsecurity "v.io/x/ref/test/security"
 )
@@ -116,7 +115,7 @@
 }
 
 func (h *proxyHandle) Start(t *testing.T, ctx *context.T, args ...string) error {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -126,9 +125,8 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	h.proxy = p
-	s := expect.NewSession(t, p.Stdout(), time.Minute)
-	s.ReadLine()
-	h.name = s.ExpectVar("PROXY_NAME")
+	p.ReadLine()
+	h.name = p.ExpectVar("PROXY_NAME")
 	if len(h.name) == 0 {
 		t.Fatalf("failed to get PROXY_NAME from proxyd")
 	}
diff --git a/profiles/internal/rt/mgmt_test.go b/profiles/internal/rt/mgmt_test.go
index 28e48d5..8f437f8 100644
--- a/profiles/internal/rt/mgmt_test.go
+++ b/profiles/internal/rt/mgmt_test.go
@@ -114,7 +114,7 @@
 // TestNoWaiters verifies that the child process exits in the absence of any
 // wait channel being registered with its runtime.
 func TestNoWaiters(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -123,7 +123,7 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	expect.NewSession(t, h.Stdout(), time.Minute).Expect("ready")
+	h.Expect("ready")
 	want := fmt.Sprintf("exit status %d", v23.UnhandledStopExitCode)
 	if err = h.Shutdown(os.Stderr, os.Stderr); err == nil || err.Error() != want {
 		t.Errorf("got %v, want %s", err, want)
@@ -146,7 +146,7 @@
 // TestForceStop verifies that ForceStop causes the child process to exit
 // immediately.
 func TestForceStop(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -155,8 +155,7 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("ready")
+	h.Expect("ready")
 	err = h.Shutdown(os.Stderr, os.Stderr)
 	want := fmt.Sprintf("exit status %d", v23.UnhandledStopExitCode)
 	if err == nil || err.Error() != want {
@@ -296,7 +295,7 @@
 	ctx, shutdown := test.InitForTest()
 
 	configServer, configServiceName, ch := createConfigServer(t, ctx)
-	sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx))
+	sh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/profiles/internal/rt/rt_test.go b/profiles/internal/rt/rt_test.go
index 7667bee..d16bb8b 100644
--- a/profiles/internal/rt/rt_test.go
+++ b/profiles/internal/rt/rt_test.go
@@ -64,7 +64,7 @@
 }
 
 func TestInitArgs(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -73,8 +73,7 @@
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect(fmt.Sprintf("name=veyron "+
+	h.Expect(fmt.Sprintf("name=veyron "+
 		"logdirs=[%s] "+
 		"logtostderr=true "+
 		"alsologtostderr=true "+
@@ -85,8 +84,8 @@
 		"log_backtrace_at=:0",
 		os.TempDir()))
 	h.CloseStdin()
-	s.Expect("done")
-	s.ExpectEOF()
+	h.Expect("done")
+	h.ExpectEOF()
 	h.Shutdown(os.Stderr, os.Stderr)
 }
 
@@ -139,7 +138,7 @@
 		return err
 	}
 	fmt.Fprintf(stdout, "RUNNER_DEFAULT_BLESSING=%v\n", defaultBlessing(p))
-	sh, err := modules.NewShell(ctx, p)
+	sh, err := modules.NewShell(ctx, p, false, nil)
 	if err != nil {
 		return err
 	}
@@ -162,7 +161,7 @@
 }
 
 func TestPrincipalInheritance(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -186,10 +185,9 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	runnerBlessing := s.ExpectVar("RUNNER_DEFAULT_BLESSING")
-	principalBlessing := s.ExpectVar("DEFAULT_BLESSING")
-	if err := s.Error(); err != nil {
+	runnerBlessing := h.ExpectVar("RUNNER_DEFAULT_BLESSING")
+	principalBlessing := h.ExpectVar("DEFAULT_BLESSING")
+	if err := h.Error(); err != nil {
 		t.Fatalf("failed to read input from children: %s", err)
 	}
 	h.Shutdown(os.Stdout, os.Stderr)
@@ -224,7 +222,7 @@
 
 	// We create two shells -- one initializing the principal for a child process
 	// via a credentials directory and the other via an agent.
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -233,7 +231,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	agentSh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx))
+	agentSh, err := modules.NewShell(ctx, v23.GetPrincipal(ctx), testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/profiles/internal/rt/shutdown_test.go b/profiles/internal/rt/shutdown_test.go
index 6fec783..6b4282e 100644
--- a/profiles/internal/rt/shutdown_test.go
+++ b/profiles/internal/rt/shutdown_test.go
@@ -6,12 +6,10 @@
 	"os"
 	"syscall"
 	"testing"
-	"time"
 
 	"v.io/v23"
 
 	"v.io/x/ref/lib/signals"
-	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 )
 
@@ -26,7 +24,7 @@
 }
 
 func newShell(t *testing.T) *modules.Shell {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -39,14 +37,13 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.Expect("Received signal interrupt")
-	s.Expect("Interruptible cleanup")
-	s.Expect("Deferred cleanup")
+	h.Expect("Received signal interrupt")
+	h.Expect("Interruptible cleanup")
+	h.Expect("Deferred cleanup")
 	fmt.Fprintln(h.Stdin(), "close")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestSimpleServerLocalStop verifies that sending a local stop command to the
@@ -55,14 +52,13 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	fmt.Fprintln(h.Stdin(), "stop")
-	s.Expect(fmt.Sprintf("Received signal %s", v23.LocalStop))
-	s.Expect("Interruptible cleanup")
-	s.Expect("Deferred cleanup")
+	h.Expect(fmt.Sprintf("Received signal %s", v23.LocalStop))
+	h.Expect("Interruptible cleanup")
+	h.Expect("Deferred cleanup")
 	fmt.Fprintln(h.Stdin(), "close")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestSimpleServerDoubleSignal verifies that sending a succession of two
@@ -72,10 +68,9 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.Expect("Received signal interrupt")
+	h.Expect("Received signal interrupt")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
 	err := h.Shutdown(os.Stdout, cstderr)
 	if err == nil {
@@ -92,10 +87,9 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	fmt.Fprintln(h.Stdin(), "forcestop")
-	s.Expect("straight exit")
+	h.Expect("straight exit")
 	err := h.Shutdown(os.Stdout, cstderr)
 	if err == nil {
 		t.Fatalf("expected an error")
@@ -111,8 +105,7 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("simpleServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGKILL)
 	err := h.Shutdown(os.Stdout, cstderr)
 	if err == nil {
@@ -131,18 +124,17 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.Expect("Received signal interrupt")
-	s.ExpectSetRE("Sequential blocking cleanup",
+	h.Expect("Received signal interrupt")
+	h.ExpectSetRE("Sequential blocking cleanup",
 		"Sequential interruptible cleanup",
 		"Parallel blocking cleanup1",
 		"Parallel blocking cleanup2",
 		"Parallel interruptible cleanup1",
 		"Parallel interruptible cleanup2")
 	fmt.Fprintln(h.Stdin(), "close")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestComplexServerLocalStop verifies that sending a local stop command to the
@@ -153,12 +145,11 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 
 	fmt.Fprintln(h.Stdin(), "stop")
-	s.Expect(fmt.Sprintf("Stop %s", v23.LocalStop))
-	s.ExpectSetRE(
+	h.Expect(fmt.Sprintf("Stop %s", v23.LocalStop))
+	h.ExpectSetRE(
 		"Sequential blocking cleanup",
 		"Sequential interruptible cleanup",
 		"Parallel blocking cleanup1",
@@ -167,7 +158,7 @@
 		"Parallel interruptible cleanup2",
 	)
 	fmt.Fprintln(h.Stdin(), "close")
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 // TestComplexServerDoubleSignal verifies that sending a succession of two
@@ -180,12 +171,11 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.Expect("Received signal interrupt")
+	h.Expect("Received signal interrupt")
 	syscall.Kill(h.Pid(), syscall.SIGINT)
-	s.ExpectSetEventuallyRE(
+	h.ExpectSetEventuallyRE(
 		"Sequential blocking cleanup",
 		"Parallel blocking cleanup1",
 		"Parallel blocking cleanup2")
@@ -204,10 +194,9 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	fmt.Fprintln(h.Stdin(), "forcestop")
-	s.Expect("straight exit")
+	h.Expect("straight exit")
 	err := h.Shutdown(os.Stdout, cstderr)
 	if err == nil {
 		t.Fatalf("expected an error")
@@ -223,8 +212,7 @@
 	sh := newShell(t)
 	defer sh.Cleanup(os.Stdout, cstderr)
 	h, _ := sh.Start("complexServerProgram", nil)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("Ready")
+	h.Expect("Ready")
 	syscall.Kill(h.Pid(), syscall.SIGKILL)
 	err := h.Shutdown(os.Stdout, cstderr)
 	if err == nil {
diff --git a/profiles/internal/rt/signal_test.go b/profiles/internal/rt/signal_test.go
index 0aa0301..3d53154 100644
--- a/profiles/internal/rt/signal_test.go
+++ b/profiles/internal/rt/signal_test.go
@@ -11,7 +11,6 @@
 
 	_ "v.io/x/ref/profiles"
 	"v.io/x/ref/test"
-	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 )
 
@@ -43,7 +42,7 @@
 }
 
 func TestWithRuntime(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -53,30 +52,30 @@
 		t.Fatalf("unexpected error: %s", err)
 	}
 	defer h.Shutdown(os.Stderr, os.Stderr)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("ready")
+	h.Expect("ready")
 	syscall.Kill(h.Pid(), syscall.SIGHUP)
 	h.Stdin().Write([]byte("foo\n"))
-	s.Expect("foo")
+	h.Expect("foo")
 	h.CloseStdin()
-	s.ExpectEOF()
+	h.ExpectEOF()
 }
 
 func TestWithoutRuntime(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	defer sh.Cleanup(os.Stderr, os.Stderr)
-	h, err := sh.Start("withoutRuntime", nil)
+	opts := sh.DefaultStartOpts()
+	opts.ShutdownTimeout = 5 * time.Second
+	h, err := sh.StartWithOpts(opts, nil, "withoutRuntime")
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
 	defer h.Shutdown(os.Stderr, os.Stderr)
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
-	s.Expect("ready")
+	h.Expect("ready")
 	syscall.Kill(h.Pid(), syscall.SIGHUP)
-	s.ExpectEOF()
+	h.ExpectEOF()
 	err = h.Shutdown(os.Stderr, os.Stderr)
 	want := "exit status 2"
 	if err == nil || err.Error() != want {
diff --git a/security/agent/agent_test.go b/security/agent/agent_test.go
index 11f5e14..a9442bf 100644
--- a/security/agent/agent_test.go
+++ b/security/agent/agent_test.go
@@ -14,7 +14,6 @@
 	"v.io/x/ref/security/agent"
 	"v.io/x/ref/security/agent/server"
 	"v.io/x/ref/test"
-	"v.io/x/ref/test/expect"
 	"v.io/x/ref/test/modules"
 	tsecurity "v.io/x/ref/test/security"
 
@@ -142,7 +141,7 @@
 	ctx, shutdown := test.InitForTest()
 
 	// This starts an agent
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -152,11 +151,10 @@
 		t.Fatal(err)
 	}
 
-	s := expect.NewSession(t, h.Stdout(), time.Minute)
 	fmt.Fprintf(os.Stderr, "reading var...\n")
-	s.ExpectVar("DEFAULT_BLESSING")
+	h.ExpectVar("DEFAULT_BLESSING")
 	fmt.Fprintf(os.Stderr, "read\n")
-	if err := s.Error(); err != nil {
+	if err := h.Error(); err != nil {
 		t.Fatalf("failed to read input: %s", err)
 	}
 	fmt.Fprintf(os.Stderr, "shutting down...\n")
diff --git a/security/flag/flag_test.go b/security/flag/flag_test.go
index 107532e..4e9c29b 100644
--- a/security/flag/flag_test.go
+++ b/security/flag/flag_test.go
@@ -59,7 +59,7 @@
 }
 
 func TestNewAuthorizerOrDie(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/services/mgmt/lib/testutil/modules.go b/services/mgmt/lib/testutil/modules.go
index 0b779a2..915f26f 100644
--- a/services/mgmt/lib/testutil/modules.go
+++ b/services/mgmt/lib/testutil/modules.go
@@ -52,7 +52,7 @@
 // CreateShellAndMountTable builds a new modules shell and its
 // associated mount table.
 func CreateShellAndMountTable(t *testing.T, ctx *context.T, p security.Principal) (*modules.Shell, func()) {
-	sh, err := modules.NewExpectShell(ctx, p, t, testing.Verbose())
+	sh, err := modules.NewShell(ctx, p, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/test/modules/core/core_test.go b/test/modules/core/core_test.go
index 9ebecb8..f114981 100644
--- a/test/modules/core/core_test.go
+++ b/test/modules/core/core_test.go
@@ -46,7 +46,7 @@
 
 func newShell(t *testing.T) (*modules.Shell, func()) {
 	ctx, shutdown := test.InitForTest()
-	sh, err := modules.NewExpectShell(ctx, nil, t, testing.Verbose())
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/test/modules/examples_test.go b/test/modules/examples_test.go
index 9fd1f24..299ec71 100644
--- a/test/modules/examples_test.go
+++ b/test/modules/examples_test.go
@@ -31,7 +31,7 @@
 		return
 	}
 	// Parent process.
-	sh, _ := modules.NewShell(ctx, nil)
+	sh, _ := modules.NewShell(ctx, nil, false, nil)
 	defer sh.Cleanup(nil, nil)
 	h, _ := sh.Start("echo", nil, "a", "b")
 	h.Shutdown(os.Stdout, os.Stderr)
@@ -45,7 +45,7 @@
 	defer shutdown()
 	// DispatchAndExit will call os.Exit(0) when executed within the child.
 	modules.DispatchAndExit()
-	sh, _ := modules.NewShell(ctx, nil)
+	sh, _ := modules.NewShell(ctx, nil, false, nil)
 	defer sh.Cleanup(nil, nil)
 	h, _ := sh.Start("echo", nil, "c", "d")
 	h.Shutdown(os.Stdout, os.Stderr)
diff --git a/test/modules/modules_internal_test.go b/test/modules/modules_internal_test.go
index 38ef18e..0585238 100644
--- a/test/modules/modules_internal_test.go
+++ b/test/modules/modules_internal_test.go
@@ -33,7 +33,7 @@
 
 	defer shutdown()
 
-	sh, err := NewShell(ctx, nil)
+	sh, err := NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/test/modules/modules_test.go b/test/modules/modules_test.go
index 1aece64..108eba7 100644
--- a/test/modules/modules_test.go
+++ b/test/modules/modules_test.go
@@ -148,11 +148,15 @@
 	defer func() {
 		var stdout, stderr bytes.Buffer
 		sh.Cleanup(&stdout, &stderr)
-		if len(stdout.String()) != 0 {
-			t.Errorf("unexpected stdout: %q", stdout.String())
+		want := ""
+		if testing.Verbose() {
+			want = "---- Shell Cleanup ----\n"
 		}
-		if len(stderr.String()) != 0 {
-			t.Errorf("unexpected stderr: %q", stderr.String())
+		if got := stdout.String(); got != "" && got != want {
+			t.Errorf("got %q, want %q", got, want)
+		}
+		if got := stderr.String(); got != "" && got != want {
+			t.Errorf("got %q, want %q", got, want)
 		}
 	}()
 	scanner := bufio.NewScanner(h.Stdout())
@@ -206,7 +210,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -220,7 +224,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -238,7 +242,7 @@
 
 	p := security.NewPrincipal("myshell")
 	cleanDebug := p.BlessingStore().DebugString()
-	sh, err := modules.NewShell(ctx, p)
+	sh, err := modules.NewShell(ctx, p, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -258,7 +262,7 @@
 	defer shutdown()
 
 	root := security.NewIDProvider("myshell")
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -306,7 +310,7 @@
 func TestNoAgent(t *testing.T) {
 	creds, _ := security.NewCredentials("noagent")
 	defer os.RemoveAll(creds)
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -321,8 +325,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	//fmt.Fprintf(os.Stderr, "B\n")
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -341,7 +344,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -355,7 +358,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -398,7 +401,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, false, t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -413,7 +416,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, false, t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -442,7 +445,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -478,7 +481,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, false, t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -490,7 +493,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -517,7 +520,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -572,7 +575,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -621,7 +624,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -641,7 +644,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -679,7 +682,7 @@
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
 
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -728,7 +731,7 @@
 func TestLIFO(t *testing.T) {
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
-	sh, err := modules.NewShell(ctx, nil)
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -759,7 +762,7 @@
 }
 
 func TestStartOpts(t *testing.T) {
-	sh, err := modules.NewShell(nil, nil)
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -795,7 +798,7 @@
 }
 
 func TestEmbeddedSession(t *testing.T) {
-	sh, err := modules.NewExpectShell(nil, nil, t, testing.Verbose())
+	sh, err := modules.NewShell(nil, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
@@ -808,7 +811,7 @@
 func TestCredentialsAndNoExec(t *testing.T) {
 	ctx, shutdown := test.InitForTest()
 	defer shutdown()
-	sh, err := modules.NewExpectShell(ctx, nil, t, testing.Verbose())
+	sh, err := modules.NewShell(ctx, nil, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("unexpected error: %s", err)
 	}
diff --git a/test/modules/shell.go b/test/modules/shell.go
index 4dc7e43..7878550 100644
--- a/test/modules/shell.go
+++ b/test/modules/shell.go
@@ -199,13 +199,23 @@
 // If p is non-nil, any child process created has its principal blessed
 // by the default blessings of 'p', Else any child process created has its
 // principal blessed by the default blessings of ctx's principal.
-func NewShell(ctx *context.T, p security.Principal) (*Shell, error) {
+//
+// If verbosity is true additional debugging info will be displayed,
+// in particular by the Shutdown.
+//
+// If t is non-nil, then the expect Session created for every invocation
+// will be constructed with that value of t unless overridden by a
+// StartOpts provided to that invocation. Providing a non-nil value of
+// t enables expect.Session to call t.Error, Errorf and Log.
+func NewShell(ctx *context.T, p security.Principal, verbosity bool, t expect.Testing) (*Shell, error) {
 	sh := &Shell{
 		env:              make(map[string]string),
 		handles:          make(map[Handle]struct{}),
 		config:           exec.NewConfig(),
 		defaultStartOpts: defaultStartOpts,
+		sessionVerbosity: verbosity,
 	}
+	sh.defaultStartOpts = sh.defaultStartOpts.WithSessions(t, time.Minute)
 	if ctx == nil {
 		return sh, nil
 	}
@@ -229,18 +239,6 @@
 	return sh, nil
 }
 
-// NewExpectShell creates a new instance of Shell as per NewShell, but with
-// the default StartOpts set to include the specified expect.Testing parameter.
-func NewExpectShell(ctx *context.T, p security.Principal, t expect.Testing, verbosity bool) (*Shell, error) {
-	sh, err := NewShell(ctx, p)
-	if err != nil {
-		return nil, err
-	}
-	sh.sessionVerbosity = verbosity
-	sh.SetDefaultStartOpts(DefaultStartOpts().WithSessions(t, time.Minute))
-	return sh, nil
-}
-
 // DefaultStartOpts returns the current StartOpts stored with the Shell.
 func (sh *Shell) DefaultStartOpts() StartOpts {
 	return sh.defaultStartOpts
diff --git a/test/v23tests/v23tests.go b/test/v23tests/v23tests.go
index cac131c..3cc0bb6 100644
--- a/test/v23tests/v23tests.go
+++ b/test/v23tests/v23tests.go
@@ -500,7 +500,7 @@
 		t.Fatalf("failed to set principal: %v", err)
 	}
 
-	shell, err := modules.NewShell(ctx, principal)
+	shell, err := modules.NewShell(ctx, principal, testing.Verbose(), t)
 	if err != nil {
 		t.Fatalf("NewShell() failed: %v", err)
 	}
diff --git a/test/v23tests/v23tests_test.go b/test/v23tests/v23tests_test.go
index 3acd20e..1af5d02 100644
--- a/test/v23tests/v23tests_test.go
+++ b/test/v23tests/v23tests_test.go
@@ -112,7 +112,7 @@
 }
 
 func TestDeferHandling(t *testing.T) {
-	sh, _ := modules.NewShell(nil, nil)
+	sh, _ := modules.NewShell(nil, nil, testing.Verbose(), t)
 	child, err := sh.Start("RunIntegrationTestInChild", nil, "--test.run=TestHelperProcess", "--v23.tests")
 	if err != nil {
 		t.Fatal(err)