github.com/tilt-dev/wat@v0.0.2-0.20180626175338-9349b638e250/cli/wat/plugin_pytest.go (about) 1 package wat 2 3 import ( 4 "context" 5 "os/exec" 6 7 "fmt" 8 "regexp" 9 ) 10 11 var rePrefix = regexp.MustCompile("(^|/)test_(.*)\\.py") 12 var rePostfix = regexp.MustCompile("(.*)_test\\.py") 13 var testRegexps = []*regexp.Regexp{rePrefix, rePostfix} 14 15 type PluginPytest struct{} 16 17 func (PluginPytest) name() string { return "python+pytest populate" } 18 19 func (PluginPytest) run(ctx context.Context, root string) ([]WatCommand, error) { 20 // 1. is pytest relevant? 21 if !projUsesPytest(ctx, root) { 22 return nil, nil 23 } 24 25 // 2. where are the test files? 26 files, err := findTestFiles(ctx, root) 27 if err != nil { 28 return nil, fmt.Errorf("findTestFiles: %v", err) 29 } 30 31 // 3. which tests --> which files? 32 watCmds := []WatCommand{} 33 for _, f := range files { 34 filePattern := testFileToPattern(root, f.name) 35 watCmds = append(watCmds, WatCommand{ 36 Command: fmt.Sprintf("pytest %s", f.name), 37 FilePattern: filePattern, 38 }) 39 } 40 41 return watCmds, nil 42 } 43 44 // Here's the naive implementation. Other possibilities: 45 // a. are there py files? 46 // b. is some other framework configured here that takes precedence? 47 // c. pytest-related files in .gitignore, requirements.txt, setup.py? 48 // d. config files 49 // + path/pytest.ini 50 // + path/setup.cfg (must also contain [tool:pytest] section to match) 51 // + path/tox.ini (must also contain [pytest] section to match) 52 // + pytest.ini 53 func projUsesPytest(ctx context.Context, root string) bool { 54 // is there a pytest executable? 55 cmd := exec.CommandContext(ctx, "python", "-c", "import pytest") 56 err := cmd.Run() 57 if err != nil { 58 return false 59 } 60 61 return true 62 } 63 64 // This is the naive function that just finds test_*.py files, returns their 65 // invocations (NOT caring about associated code) 66 func findTestFiles(ctx context.Context, root string) ([]fileInfo, error) { 67 allFiles, err := walkDir(root) 68 if err != nil { 69 return nil, fmt.Errorf("walkDir: %v", err) 70 } 71 return filterFilesMatchAny(allFiles, testRegexps), nil 72 } 73 74 func testFileToPattern(root, test string) string { 75 // Fallthrough: associate with all .py files 76 return "**/*.py" 77 } 78 79 func baseFile(test string) string { 80 if substrs := rePrefix.FindStringSubmatch(test); len(substrs) > 1 { 81 fmt.Println(substrs) 82 return fmt.Sprintf("%s.py", substrs[1]) 83 } 84 if substrs := rePostfix.FindStringSubmatch(test); len(substrs) > 1 { 85 fmt.Println(substrs) 86 return fmt.Sprintf("%s.py", substrs[1]) 87 } 88 return "" 89 } 90 91 var _ plugin = PluginPytest{}