github.com/jacobsoderblom/buffalo@v0.11.0/buffalo/cmd/test.go (about) 1 package cmd 2 3 import ( 4 "bytes" 5 "io" 6 "io/ioutil" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "regexp" 11 "strings" 12 13 "github.com/gobuffalo/buffalo/meta" 14 "github.com/gobuffalo/envy" 15 "github.com/pkg/errors" 16 "github.com/sirupsen/logrus" 17 18 "github.com/gobuffalo/pop" 19 "github.com/spf13/cobra" 20 ) 21 22 const vendorPattern = "/vendor/" 23 24 var vendorRegex = regexp.MustCompile(vendorPattern) 25 26 func init() { 27 decorate("test", testCmd) 28 RootCmd.AddCommand(testCmd) 29 } 30 31 var testCmd = &cobra.Command{ 32 Use: "test", 33 Short: "Runs the tests for your Buffalo app", 34 DisableFlagParsing: true, 35 RunE: func(c *cobra.Command, args []string) error { 36 os.Setenv("GO_ENV", "test") 37 if _, err := os.Stat("database.yml"); err == nil { 38 // there's a database 39 test, err := pop.Connect("test") 40 if err != nil { 41 return errors.WithStack(err) 42 } 43 44 // drop the test db: 45 test.Dialect.DropDB() 46 47 // create the test db: 48 err = test.Dialect.CreateDB() 49 if err != nil { 50 return errors.WithStack(err) 51 } 52 53 if schema := findSchema(); schema != nil { 54 err = test.Dialect.LoadSchema(schema) 55 if err != nil { 56 return errors.WithStack(err) 57 } 58 } 59 } 60 return testRunner(args) 61 }, 62 } 63 64 func findSchema() io.Reader { 65 if f, err := os.Open(filepath.Join("migrations", "schema.sql")); err == nil { 66 return f 67 } 68 if dev, err := pop.Connect("development"); err == nil { 69 schema := &bytes.Buffer{} 70 if err = dev.Dialect.DumpSchema(schema); err == nil { 71 return schema 72 } 73 } 74 75 if test, err := pop.Connect("test"); err == nil { 76 if err := test.MigrateUp("./migrations"); err == nil { 77 if f, err := os.Open(filepath.Join("migrations", "schema.sql")); err == nil { 78 return f 79 } 80 } 81 } 82 return nil 83 } 84 85 func testRunner(args []string) error { 86 var mFlag bool 87 cargs := []string{} 88 pargs := []string{} 89 var larg string 90 for i, a := range args { 91 switch a { 92 case "-run": 93 cargs = append(cargs, "-run", args[i+1]) 94 case "-m": 95 mFlag = true 96 cargs = append(cargs, "-testify.m", args[i+1]) 97 case "-v": 98 cargs = append(cargs, "-v") 99 default: 100 if larg != "-run" && larg != "-m" { 101 pargs = append(pargs, a) 102 } 103 } 104 larg = a 105 } 106 107 cmd := newTestCmd(cargs) 108 if mFlag { 109 return mFlagRunner(cargs, pargs) 110 } 111 112 pkgs, err := testPackages(pargs) 113 if err != nil { 114 return errors.WithStack(err) 115 } 116 cmd.Args = append(cmd.Args, pkgs...) 117 logrus.Info(strings.Join(cmd.Args, " ")) 118 return cmd.Run() 119 } 120 121 func mFlagRunner(args []string, pargs []string) error { 122 app := meta.New(".") 123 pwd, _ := os.Getwd() 124 defer os.Chdir(pwd) 125 126 pkgs, err := testPackages(pargs) 127 if err != nil { 128 return errors.WithStack(err) 129 } 130 var errs bool 131 for _, p := range pkgs { 132 os.Chdir(pwd) 133 if p == app.PackagePkg { 134 continue 135 } 136 cmd := newTestCmd(args) 137 p = strings.TrimPrefix(p, app.PackagePkg+string(filepath.Separator)) 138 logrus.Info(strings.Join(cmd.Args, " ")) 139 os.Chdir(p) 140 if err := cmd.Run(); err != nil { 141 errs = true 142 } 143 } 144 if errs { 145 return errors.New("errors running tests") 146 } 147 return nil 148 } 149 150 func testPackages(givenArgs []string) ([]string, error) { 151 // If there are args, then assume these are the packages to test. 152 // 153 // Instead of always returning all packages from 'go list ./...', just 154 // return the given packages in this case 155 if len(givenArgs) > 0 { 156 return givenArgs, nil 157 } 158 args := []string{} 159 out, err := exec.Command(envy.Get("GO_BIN", "go"), "list", "./...").Output() 160 if err != nil { 161 return args, err 162 } 163 pkgs := bytes.Split(bytes.TrimSpace(out), []byte("\n")) 164 for _, p := range pkgs { 165 if !vendorRegex.Match(p) { 166 args = append(args, string(p)) 167 } 168 } 169 return args, nil 170 } 171 172 func newTestCmd(args []string) *exec.Cmd { 173 cargs := []string{"test", "-p", "1"} 174 if b, err := ioutil.ReadFile("database.yml"); err == nil { 175 if bytes.Contains(b, []byte("sqlite")) { 176 cargs = append(cargs, "-tags", "sqlite") 177 } 178 } 179 cargs = append(cargs, args...) 180 cmd := exec.Command(envy.Get("GO_BIN", "go"), cargs...) 181 cmd.Stdin = os.Stdin 182 cmd.Stdout = os.Stdout 183 cmd.Stderr = os.Stderr 184 return cmd 185 }