예제 #1
0
파일: harness.go 프로젝트: pyanfield/revel
// Return a reverse proxy that forwards requests to the given port.
func NewHarness() *Harness {
	// Get a template loader to render errors.
	// Prefer the app's views/errors directory, and fall back to the stock error pages.
	revel.MainTemplateLoader = revel.NewTemplateLoader(
		[]string{path.Join(revel.RevelPath, "templates")})
	revel.MainTemplateLoader.Refresh()

	addr := revel.HttpAddr
	port := revel.Config.IntDefault("harness.port", 0)

	if port == 0 {
		port = getFreePort()
	}

	serverUrl, _ := url.ParseRequestURI(fmt.Sprintf("http://%s:%d", addr, port))

	harness := &Harness{
		port:       port,
		serverHost: serverUrl.String()[len("http://"):],
		proxy:      httputil.NewSingleHostReverseProxy(serverUrl),
	}
	return harness
}
예제 #2
0
파일: test.go 프로젝트: pyanfield/revel
func testApp(args []string) {
	var err error
	if len(args) == 0 {
		errorf("No import path given.\nRun 'revel help test' for usage.\n")
	}

	mode := "dev"
	if len(args) == 2 {
		mode = args[1]
	}

	// Find and parse app.conf
	revel.Init(mode, args[0], "")

	// Ensure that the testrunner is loaded in this mode.
	testRunnerFound := false
	for _, module := range revel.Modules {
		if module.ImportPath == "github.com/pyanfield/revel/modules/testrunner" {
			testRunnerFound = true
			break
		}
	}
	if !testRunnerFound {
		errorf(`Error: The testrunner module is not running.

You can add it to a run mode configuration with the following line: 

	module.testrunner = github.com/pyanfield/revel/modules/testrunner

`)
	}

	// Create a directory to hold the test result files.
	resultPath := path.Join(revel.BasePath, "test-results")
	if err = os.RemoveAll(resultPath); err != nil {
		errorf("Failed to remove test result directory %s: %s", resultPath, err)
	}
	if err = os.Mkdir(resultPath, 0777); err != nil {
		errorf("Failed to create test result directory %s: %s", resultPath, err)
	}

	// Direct all the output into a file in the test-results directory.
	file, err := os.OpenFile(path.Join(resultPath, "app.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
	if err != nil {
		errorf("Failed to create log file: %s", err)
	}

	app, reverr := harness.Build()
	if reverr != nil {
		errorf("Error building: %s", reverr)
	}
	cmd := app.Cmd()
	cmd.Stderr = file
	cmd.Stdout = file

	// Start the app...
	cmd.Start()
	defer cmd.Kill()
	revel.INFO.Printf("Testing %s (%s) in %s mode\n", revel.AppName, revel.ImportPath, mode)

	// Get a list of tests.
	var testSuites []controllers.TestSuiteDesc
	baseUrl := fmt.Sprintf("http://127.0.0.1:%d", revel.HttpPort)
	resp, err := http.Get(baseUrl + "/@tests.list")
	if err != nil {
		errorf("Failed to request test list: %s", err)
	}
	defer resp.Body.Close()
	json.NewDecoder(resp.Body).Decode(&testSuites)

	fmt.Printf("\n%d test suite%s to run.\n", len(testSuites), pluralize(len(testSuites), "", "s"))
	fmt.Println()

	// Load the result template, which we execute for each suite.
	TemplateLoader := revel.NewTemplateLoader(revel.TemplatePaths)
	if err := TemplateLoader.Refresh(); err != nil {
		errorf("Failed to compile templates: %s", err)
	}
	resultTemplate, err := TemplateLoader.Template("TestRunner/SuiteResult.html")
	if err != nil {
		errorf("Failed to load suite result template: %s", err)
	}

	// Run each suite.
	overallSuccess := true
	for _, suite := range testSuites {
		// Print the name of the suite we're running.
		name := suite.Name
		if len(name) > 22 {
			name = name[:19] + "..."
		}
		fmt.Printf("%-22s", name)

		// Run every test.
		startTime := time.Now()
		suiteResult := controllers.TestSuiteResult{Name: suite.Name, Passed: true}
		for _, test := range suite.Tests {
			testUrl := baseUrl + "/@tests/" + suite.Name + "/" + test.Name
			resp, err := http.Get(testUrl)
			if err != nil {
				errorf("Failed to fetch test result at url %s: %s", testUrl, err)
			}
			defer resp.Body.Close()

			var testResult controllers.TestResult
			json.NewDecoder(resp.Body).Decode(&testResult)
			if !testResult.Passed {
				suiteResult.Passed = false
			}
			suiteResult.Results = append(suiteResult.Results, testResult)
		}
		overallSuccess = overallSuccess && suiteResult.Passed

		// Print result.  (Just PASSED or FAILED, and the time taken)
		suiteResultStr, suiteAlert := "PASSED", ""
		if !suiteResult.Passed {
			suiteResultStr, suiteAlert = "FAILED", "!"
		}
		fmt.Printf("%8s%3s%6ds\n", suiteResultStr, suiteAlert, int(time.Since(startTime).Seconds()))

		// Create the result HTML file.
		suiteResultFilename := path.Join(resultPath,
			fmt.Sprintf("%s.%s.html", suite.Name, strings.ToLower(suiteResultStr)))
		suiteResultFile, err := os.Create(suiteResultFilename)
		if err != nil {
			errorf("Failed to create result file %s: %s", suiteResultFilename, err)
		}
		if err = resultTemplate.Render(suiteResultFile, suiteResult); err != nil {
			errorf("Failed to render result template: %s", err)
		}
	}

	fmt.Println()
	if overallSuccess {
		writeResultFile(resultPath, "result.passed", "passed")
		fmt.Println("All Tests Passed.")
	} else {
		writeResultFile(resultPath, "result.failed", "failed")
		errorf("Some tests failed.  See file://%s for results.", resultPath)
	}
}