Merge branch '16-test-coverage' into 'master'
Resolve "test coverage" Closes #16 See merge request slon/shad-go-private!20
This commit is contained in:
commit
629e9b3c92
44 changed files with 1020 additions and 1 deletions
85
coverme/README.md
Normal file
85
coverme/README.md
Normal file
|
@ -0,0 +1,85 @@
|
|||
## coverme
|
||||
|
||||
В этой задаче нужно покрыть простой todo-app http сервис unit тестами.
|
||||
|
||||
Необходимо покрыть все sub-package'и.
|
||||
Package main можно не тестировать.
|
||||
|
||||
Существующие файлы менять не нужно.
|
||||
Нужно создавать новые файлы с тестами.
|
||||
|
||||
Тестирующая система будет проверять code coverage.
|
||||
Порог задан в [coverage_test.go](./app/coverage_test.go)
|
||||
|
||||
Важно понимать, что coverage 100% - не решение всех проблем.
|
||||
В коде по-прежнему могут быть ошибки.
|
||||
Coverage 100% говорит ровно о том, что все строки кода выполнялись.
|
||||
Хорошие тесты в первую очередь тестируют функциональность.
|
||||
|
||||
Как посмотреть coverage:
|
||||
```
|
||||
go test -v -cover ./coverme/...
|
||||
```
|
||||
|
||||
Coverage можно выводить в html (см. ссылки), и эта функциональность поддерживается в Goland.
|
||||
|
||||
## Ссылки
|
||||
|
||||
1. cover: https://blog.golang.org/cover
|
||||
2. [gomock](https://github.com/golang/mock) для создания мока базы данных при тестировании серевера
|
||||
3. [httptest.ResponseRecorder](https://golang.org/pkg/net/http/httptest/#ResponseRecorder) для тестирования handler'ов сервера
|
||||
4. [httptest.Server](https://golang.org/pkg/net/http/httptest/#Server) для тестирования клинета
|
||||
5. Если вы ждёте, когда же выложат лекцию: https://www.youtube.com/watch?v=ndmB0bj7eyw
|
||||
|
||||
## O сервисе
|
||||
|
||||
Todo-app с минимальной функциональностью + client.
|
||||
|
||||
Запуск:
|
||||
```
|
||||
✗ go run ./coverme/main.go -port 6029
|
||||
```
|
||||
|
||||
Health check:
|
||||
```
|
||||
✗ curl -i -X GET localhost:6029/
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Date: Thu, 19 Mar 2020 21:46:02 GMT
|
||||
Content-Length: 24
|
||||
|
||||
"API is up and working!"
|
||||
```
|
||||
|
||||
Создать новое todo:
|
||||
```
|
||||
✗ curl -i localhost:6029/todo/create -d '{"title":"A","content":"a"}'
|
||||
HTTP/1.1 201 Created
|
||||
Content-Type: application/json
|
||||
Date: Thu, 19 Mar 2020 21:41:31 GMT
|
||||
Content-Length: 51
|
||||
|
||||
{"id":0,"title":"A","content":"a","finished":false}
|
||||
```
|
||||
|
||||
Получить todo по id:
|
||||
```
|
||||
✗ curl -i localhost:6029/todo/0
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Date: Thu, 19 Mar 2020 21:44:17 GMT
|
||||
Content-Length: 51
|
||||
|
||||
{"id":0,"title":"A","content":"a","finished":false}
|
||||
```
|
||||
|
||||
Получить все todo:
|
||||
```
|
||||
✗ curl -i -X GET localhost:6029/todo
|
||||
HTTP/1.1 200 OK
|
||||
Content-Type: application/json
|
||||
Date: Thu, 19 Mar 2020 21:44:37 GMT
|
||||
Content-Length: 53
|
||||
|
||||
[{"id":0,"title":"A","content":"a","finished":false}]
|
||||
```
|
99
coverme/app/app.go
Normal file
99
coverme/app/app.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
// +build !change
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/handlers"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
"gitlab.com/slon/shad-go/coverme/utils"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
router *mux.Router
|
||||
db models.Storage
|
||||
}
|
||||
|
||||
func New(db models.Storage) *App {
|
||||
return &App{db: db}
|
||||
}
|
||||
|
||||
func (app *App) Start(port int) {
|
||||
app.initRoutes()
|
||||
app.run(fmt.Sprintf(":%d", port))
|
||||
}
|
||||
|
||||
func (app *App) initRoutes() {
|
||||
app.router = mux.NewRouter()
|
||||
app.router.HandleFunc("/", app.status).Methods("Get")
|
||||
app.router.HandleFunc("/todo", app.list).Methods("Get")
|
||||
app.router.HandleFunc("/todo/{id:[0-9]+}", app.getTodo).Methods("Get")
|
||||
app.router.HandleFunc("/todo/create", app.addTodo).Methods("Post")
|
||||
}
|
||||
|
||||
func (app *App) run(addr string) {
|
||||
loggedRouter := handlers.LoggingHandler(os.Stderr, app.router)
|
||||
_ = http.ListenAndServe(addr, loggedRouter)
|
||||
}
|
||||
|
||||
func (app *App) list(w http.ResponseWriter, r *http.Request) {
|
||||
todos, err := app.db.GetAll()
|
||||
if err != nil {
|
||||
utils.ServerError(w)
|
||||
return
|
||||
}
|
||||
|
||||
_ = utils.RespondJSON(w, http.StatusOK, todos)
|
||||
}
|
||||
|
||||
func (app *App) addTodo(w http.ResponseWriter, r *http.Request) {
|
||||
req := &models.AddRequest{}
|
||||
|
||||
decoder := json.NewDecoder(r.Body)
|
||||
if err := decoder.Decode(&req); err != nil {
|
||||
utils.BadRequest(w, "payload is required")
|
||||
return
|
||||
}
|
||||
defer func() { _ = r.Body.Close() }()
|
||||
|
||||
if req.Title == "" {
|
||||
utils.BadRequest(w, "title is required")
|
||||
return
|
||||
}
|
||||
|
||||
todo, err := app.db.AddTodo(req.Title, req.Content)
|
||||
if err != nil {
|
||||
utils.ServerError(w)
|
||||
return
|
||||
}
|
||||
|
||||
_ = utils.RespondJSON(w, http.StatusCreated, todo)
|
||||
}
|
||||
|
||||
func (app *App) getTodo(w http.ResponseWriter, r *http.Request) {
|
||||
id, err := strconv.Atoi(strings.TrimPrefix(r.URL.Path, "/todo/"))
|
||||
if err != nil {
|
||||
utils.BadRequest(w, "ID must be an int")
|
||||
return
|
||||
}
|
||||
|
||||
todo, err := app.db.GetTodo(models.ID(id))
|
||||
if err != nil {
|
||||
utils.ServerError(w)
|
||||
return
|
||||
}
|
||||
|
||||
_ = utils.RespondJSON(w, http.StatusOK, todo)
|
||||
}
|
||||
|
||||
func (app *App) status(w http.ResponseWriter, r *http.Request) {
|
||||
_ = utils.RespondJSON(w, http.StatusOK, "API is up and working!")
|
||||
}
|
5
coverme/app/coverage_test.go
Normal file
5
coverme/app/coverage_test.go
Normal file
|
@ -0,0 +1,5 @@
|
|||
// +build !change
|
||||
|
||||
package app
|
||||
|
||||
// min coverage: 90%
|
70
coverme/client/client.go
Normal file
70
coverme/client/client.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
// +build !change
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
addr string
|
||||
}
|
||||
|
||||
func New(addr string) *Client {
|
||||
return &Client{addr: addr}
|
||||
}
|
||||
|
||||
func (c *Client) Add(r *models.AddRequest) (*models.Todo, error) {
|
||||
data, _ := json.Marshal(r)
|
||||
|
||||
resp, err := http.Post(c.addr+"/create", "application/json", bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusCreated {
|
||||
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var todo *models.Todo
|
||||
err = json.NewDecoder(resp.Body).Decode(&todo)
|
||||
return todo, err
|
||||
}
|
||||
|
||||
func (c *Client) Get(id models.ID) (*models.Todo, error) {
|
||||
resp, err := http.Get(c.addr + fmt.Sprintf("/todo/%d", id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var todo *models.Todo
|
||||
err = json.NewDecoder(resp.Body).Decode(&todo)
|
||||
return todo, err
|
||||
}
|
||||
|
||||
func (c *Client) List() ([]*models.Todo, error) {
|
||||
resp, err := http.Get(c.addr + "/todo")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("unexpected status code %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
var todos []*models.Todo
|
||||
err = json.NewDecoder(resp.Body).Decode(&todos)
|
||||
return todos, err
|
||||
}
|
18
coverme/main.go
Normal file
18
coverme/main.go
Normal file
|
@ -0,0 +1,18 @@
|
|||
// +build !change
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
|
||||
"gitlab.com/slon/shad-go/coverme/app"
|
||||
"gitlab.com/slon/shad-go/coverme/models"
|
||||
)
|
||||
|
||||
func main() {
|
||||
port := flag.Int("port", 8080, "port to listen")
|
||||
flag.Parse()
|
||||
|
||||
db := models.NewInMemoryStorage()
|
||||
app.New(db).Start(*port)
|
||||
}
|
70
coverme/models/storage.go
Normal file
70
coverme/models/storage.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
// +build !change
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Storage interface {
|
||||
AddTodo(string, string) (*Todo, error)
|
||||
GetTodo(ID) (*Todo, error)
|
||||
GetAll() ([]*Todo, error)
|
||||
}
|
||||
|
||||
type InMemoryStorage struct {
|
||||
mu sync.RWMutex
|
||||
todos map[ID]*Todo
|
||||
|
||||
nextID ID
|
||||
}
|
||||
|
||||
func NewInMemoryStorage() *InMemoryStorage {
|
||||
return &InMemoryStorage{
|
||||
todos: make(map[ID]*Todo),
|
||||
}
|
||||
}
|
||||
|
||||
func (s *InMemoryStorage) AddTodo(title, content string) (*Todo, error) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
id := s.nextID
|
||||
s.nextID++
|
||||
|
||||
todo := &Todo{
|
||||
ID: id,
|
||||
Title: title,
|
||||
Content: content,
|
||||
Finished: false,
|
||||
}
|
||||
|
||||
s.todos[todo.ID] = todo
|
||||
|
||||
return todo, nil
|
||||
}
|
||||
|
||||
func (s *InMemoryStorage) GetTodo(id ID) (*Todo, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
todo, ok := s.todos[id]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("todo %d not found", id)
|
||||
}
|
||||
|
||||
return todo, nil
|
||||
}
|
||||
|
||||
func (s *InMemoryStorage) GetAll() ([]*Todo, error) {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
var out []*Todo
|
||||
for _, todo := range s.todos {
|
||||
out = append(out, todo)
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
25
coverme/models/todo.go
Normal file
25
coverme/models/todo.go
Normal file
|
@ -0,0 +1,25 @@
|
|||
// +build !change
|
||||
|
||||
package models
|
||||
|
||||
type ID int
|
||||
|
||||
type AddRequest struct {
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
}
|
||||
|
||||
type Todo struct {
|
||||
ID ID `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Finished bool `json:"finished"`
|
||||
}
|
||||
|
||||
func (t *Todo) MarkFinished() {
|
||||
t.Finished = true
|
||||
}
|
||||
|
||||
func (t *Todo) MarkUnfished() {
|
||||
t.Finished = false
|
||||
}
|
32
coverme/utils/httputils.go
Normal file
32
coverme/utils/httputils.go
Normal file
|
@ -0,0 +1,32 @@
|
|||
// +build !change
|
||||
|
||||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func RespondJSON(w http.ResponseWriter, status int, data interface{}) error {
|
||||
response, err := json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(status)
|
||||
|
||||
_, _ = w.Write(response)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ServerError(w http.ResponseWriter) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = w.Write([]byte("Server encountered an error."))
|
||||
}
|
||||
|
||||
func BadRequest(w http.ResponseWriter, message string) {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
_, _ = w.Write([]byte(message))
|
||||
}
|
2
go.mod
2
go.mod
|
@ -6,6 +6,8 @@ require (
|
|||
github.com/go-resty/resty/v2 v2.1.0
|
||||
github.com/gofrs/uuid v3.2.0+incompatible
|
||||
github.com/golang/mock v1.4.1
|
||||
github.com/gorilla/handlers v1.4.2
|
||||
github.com/gorilla/mux v1.7.4
|
||||
github.com/spf13/cobra v0.0.5
|
||||
github.com/stretchr/testify v1.4.0
|
||||
go.uber.org/goleak v1.0.0
|
||||
|
|
4
go.sum
4
go.sum
|
@ -26,6 +26,10 @@ github.com/gonum/internal v0.0.0-20181124074243-f884aa714029/go.mod h1:Pu4dmpkhS
|
|||
github.com/gonum/lapack v0.0.0-20181123203213-e4cdc5a0bff9/go.mod h1:XA3DeT6rxh2EAE789SSiSJNqxPaC0aE9J8NTOI0Jo/A=
|
||||
github.com/gonum/matrix v0.0.0-20181209220409-c518dec07be9/go.mod h1:0EXg4mc1CNP0HCqCz+K4ts155PXIlUywf0wqN+GfPZw=
|
||||
github.com/googleapis/gax-go v0.0.0-20161107002406-da06d194a00e/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
|
||||
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
|
|
96
tools/testtool/commands/coverage.go
Normal file
96
tools/testtool/commands/coverage.go
Normal file
|
@ -0,0 +1,96 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/tools/cover"
|
||||
)
|
||||
|
||||
// coverageCommentPrefix is a prefix of coverage comment.
|
||||
//
|
||||
// Coverage comment has the following form:
|
||||
//
|
||||
// // min coverage: 80.5%
|
||||
const coverageCommentPrefix = "min coverage: "
|
||||
|
||||
type CoverageRequirements struct {
|
||||
Enabled bool
|
||||
Percent float64
|
||||
}
|
||||
|
||||
// getCoverageRequirements searches for comment in test files
|
||||
// that specifies test coverage requirements.
|
||||
//
|
||||
// Stops on first matching comment.
|
||||
func getCoverageRequirements(rootPackage string) *CoverageRequirements {
|
||||
files := listTestFiles(rootPackage)
|
||||
|
||||
for _, f := range files {
|
||||
if r, _ := searchCoverageComment(f); r.Enabled {
|
||||
return r
|
||||
}
|
||||
}
|
||||
|
||||
return &CoverageRequirements{}
|
||||
}
|
||||
|
||||
// searchCoverageComment searches for the first occurrence of the comment of the form
|
||||
//
|
||||
// // min coverage: 80.5%
|
||||
//
|
||||
// Stops on the first matching comment.
|
||||
func searchCoverageComment(fname string) (*CoverageRequirements, error) {
|
||||
fset := token.NewFileSet()
|
||||
|
||||
f, err := parser.ParseFile(fset, fname, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, c := range f.Comments {
|
||||
t := c.Text()
|
||||
if !strings.HasPrefix(t, coverageCommentPrefix) || !strings.HasSuffix(t, "%\n") {
|
||||
continue
|
||||
}
|
||||
t = strings.TrimPrefix(t, coverageCommentPrefix)
|
||||
t = strings.TrimSuffix(t, "%\n")
|
||||
percent, err := strconv.ParseFloat(t, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if percent < 0 || percent > 100.0 {
|
||||
continue
|
||||
}
|
||||
return &CoverageRequirements{Enabled: true, Percent: percent}, nil
|
||||
}
|
||||
|
||||
return &CoverageRequirements{}, nil
|
||||
}
|
||||
|
||||
// calCoverage calculates coverage percent for given coverage profile.
|
||||
func calCoverage(profile string) (float64, error) {
|
||||
profiles, err := cover.ParseProfiles(profile)
|
||||
if err != nil {
|
||||
return 0.0, fmt.Errorf("cannot parse coverage profile file %s: %w", profile, err)
|
||||
}
|
||||
|
||||
var total, covered int
|
||||
for _, p := range profiles {
|
||||
for _, block := range p.Blocks {
|
||||
total += block.NumStmt
|
||||
if block.Count > 0 {
|
||||
covered += block.NumStmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if total == 0 {
|
||||
return 0.0, nil
|
||||
}
|
||||
|
||||
return float64(covered) / float64(total) * 100, nil
|
||||
}
|
13
tools/testtool/commands/coverage_test.go
Normal file
13
tools/testtool/commands/coverage_test.go
Normal file
|
@ -0,0 +1,13 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_getCoverageRequirements(t *testing.T) {
|
||||
r := getCoverageRequirements("../testdata/coverage/sum")
|
||||
require.True(t, r.Enabled)
|
||||
require.Equal(t, 90.0, r.Percent)
|
||||
}
|
|
@ -242,12 +242,21 @@ func runTests(testDir, privateRepo, problem string) error {
|
|||
}
|
||||
}
|
||||
|
||||
coverageReq := getCoverageRequirements(privateRepo)
|
||||
if coverageReq.Enabled {
|
||||
log.Printf("required coverage: %.2f%%", coverageReq.Percent)
|
||||
}
|
||||
|
||||
binariesJSON, _ := json.Marshal(binaries)
|
||||
|
||||
for testPkg := range testPkgs {
|
||||
binPath := filepath.Join(binCache, randomName())
|
||||
testBinaries[testPkg] = binPath
|
||||
if err := runGo("test", "-mod", "readonly", "-tags", "private", "-c", "-o", binPath, testPkg); err != nil {
|
||||
cmd := []string{"test", "-mod", "readonly", "-tags", "private", "-c", "-o", binPath, testPkg}
|
||||
if coverageReq.Enabled {
|
||||
cmd = append(cmd, "-cover")
|
||||
}
|
||||
if err := runGo(cmd...); err != nil {
|
||||
return fmt.Errorf("error building test in %s: %w", testPkg, err)
|
||||
}
|
||||
}
|
||||
|
@ -257,6 +266,9 @@ func runTests(testDir, privateRepo, problem string) error {
|
|||
|
||||
{
|
||||
cmd := exec.Command(testBinary)
|
||||
if coverageReq.Enabled {
|
||||
cmd = exec.Command(testBinary, "-test.coverprofile", "c.out")
|
||||
}
|
||||
if currentUserIsRoot() {
|
||||
if err := sandbox(cmd); err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -273,6 +285,20 @@ func runTests(testDir, privateRepo, problem string) error {
|
|||
}
|
||||
}
|
||||
|
||||
if coverageReq.Enabled {
|
||||
log.Printf("checking coverage is at least %.2f%% for %s", coverageReq.Percent, testPkg)
|
||||
|
||||
percent, err := calCoverage(filepath.Join(testDir, relPath, "c.out"))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if percent < coverageReq.Percent {
|
||||
return fmt.Errorf("poor coverage %.2f%%; expected at least %.2f%%",
|
||||
percent, coverageReq.Percent)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
benchCmd := exec.Command(testBinary, "-test.bench=.", "-test.run=^$")
|
||||
if currentUserIsRoot() {
|
||||
|
|
22
tools/testtool/testdata/coverage/sum/subpkg/empty_test.go
vendored
Normal file
22
tools/testtool/testdata/coverage/sum/subpkg/empty_test.go
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
// This is subpkg package comment.
|
||||
package subpkg
|
||||
|
||||
// Incorrect coverage comments:
|
||||
|
||||
// min coverage: -1%
|
||||
|
||||
// min coverage: 100.001%
|
||||
|
||||
// min coverage: 100 %
|
||||
|
||||
// min coverage:10%
|
||||
|
||||
// min coverage: 19%
|
||||
|
||||
// Correct coverage comment:
|
||||
|
||||
// min coverage: 90%
|
||||
|
||||
// Testtool uses first matching comment.
|
||||
|
||||
// min coverage: 91%
|
2
tools/testtool/testdata/coverage/sum/sum.go
vendored
Normal file
2
tools/testtool/testdata/coverage/sum/sum.go
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
// This is package comment.
|
||||
package sum
|
8
tools/testtool/testdata/coverage/sum/sum_test.go
vendored
Normal file
8
tools/testtool/testdata/coverage/sum/sum_test.go
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
package sum
|
||||
|
||||
// This is a single line comment.
|
||||
|
||||
/*
|
||||
This is multiline
|
||||
comment!
|
||||
*/
|
77
tools/testtool/testdata/submissions/correct/coverme/private/.golangci.yml
vendored
Normal file
77
tools/testtool/testdata/submissions/correct/coverme/private/.golangci.yml
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 8
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
local-prefixes: gitlab.com
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- errcheck
|
||||
- gofmt
|
||||
- golint
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- scopelint
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
exclude:
|
||||
- Using the variable on range scope .* in function literal
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: true
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
17
tools/testtool/testdata/submissions/correct/coverme/private/coverme/coverage_test.go
vendored
Normal file
17
tools/testtool/testdata/submissions/correct/coverme/private/coverme/coverage_test.go
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// +build !change
|
||||
|
||||
package coverme_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/slon/shad-go/coverme"
|
||||
)
|
||||
|
||||
// min coverage: 70%
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), coverme.Sum(1, 1))
|
||||
}
|
14
tools/testtool/testdata/submissions/correct/coverme/private/coverme/service.go
vendored
Normal file
14
tools/testtool/testdata/submissions/correct/coverme/private/coverme/service.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build !change
|
||||
|
||||
package coverme
|
||||
|
||||
import "net/http"
|
||||
|
||||
func Sum(a, b int64) int64 {
|
||||
if a == 0 {
|
||||
return b
|
||||
} else if a == http.StatusOK {
|
||||
return http.StatusCreated + b - 1
|
||||
}
|
||||
return a + b
|
||||
}
|
15
tools/testtool/testdata/submissions/correct/coverme/private/coverme/solution_test.go
vendored
Normal file
15
tools/testtool/testdata/submissions/correct/coverme/private/coverme/solution_test.go
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
// +build solution
|
||||
|
||||
package coverme
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), Sum(1, 1))
|
||||
require.Equal(t, int64(1), Sum(0, 1))
|
||||
require.Equal(t, int64(202), Sum(200, 2))
|
||||
}
|
12
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/f.go
vendored
Normal file
12
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/f.go
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build !change
|
||||
|
||||
package subpkg
|
||||
|
||||
func AddOne(n int) int {
|
||||
if n == 0 {
|
||||
return 1
|
||||
} else if n == 1 {
|
||||
return 2
|
||||
}
|
||||
return n + 1
|
||||
}
|
13
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/f_test.go
vendored
Normal file
13
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/f_test.go
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
package subpkg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// min coverage: 100%
|
||||
|
||||
func TestAddOne(t *testing.T) {
|
||||
require.Equal(t, 1, AddOne(0))
|
||||
}
|
5
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/g.go
vendored
Normal file
5
tools/testtool/testdata/submissions/correct/coverme/private/coverme/subpkg/g.go
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
package subpkg
|
||||
|
||||
func AddTwo(n int) int {
|
||||
return AddOne(n + 1)
|
||||
}
|
5
tools/testtool/testdata/submissions/correct/coverme/private/go.mod
vendored
Normal file
5
tools/testtool/testdata/submissions/correct/coverme/private/go.mod
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitlab.com/slon/shad-go
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.5.1
|
11
tools/testtool/testdata/submissions/correct/coverme/private/go.sum
vendored
Normal file
11
tools/testtool/testdata/submissions/correct/coverme/private/go.sum
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
11
tools/testtool/testdata/submissions/correct/coverme/student/coverme/additional_test.go
vendored
Normal file
11
tools/testtool/testdata/submissions/correct/coverme/student/coverme/additional_test.go
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package coverme
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSum2(t *testing.T) {
|
||||
require.Equal(t, int64(202), Sum(200, 2))
|
||||
}
|
17
tools/testtool/testdata/submissions/correct/coverme/student/coverme/coverage_test.go
vendored
Normal file
17
tools/testtool/testdata/submissions/correct/coverme/student/coverme/coverage_test.go
vendored
Normal file
|
@ -0,0 +1,17 @@
|
|||
// +build !change
|
||||
|
||||
package coverme_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"gitlab.com/slon/shad-go/coverme"
|
||||
)
|
||||
|
||||
// min coverage: 70%
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), coverme.Sum(1, 1))
|
||||
}
|
14
tools/testtool/testdata/submissions/correct/coverme/student/coverme/service.go
vendored
Normal file
14
tools/testtool/testdata/submissions/correct/coverme/student/coverme/service.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build !change
|
||||
|
||||
package coverme
|
||||
|
||||
import "net/http"
|
||||
|
||||
func Sum(a, b int64) int64 {
|
||||
if a == 0 {
|
||||
return b
|
||||
} else if a == http.StatusOK {
|
||||
return http.StatusCreated + b - 1
|
||||
}
|
||||
return a + b
|
||||
}
|
16
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/additional_test.go
vendored
Normal file
16
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/additional_test.go
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
package subpkg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAddOne_2(t *testing.T) {
|
||||
require.Equal(t, 2, AddOne(1))
|
||||
require.Equal(t, 30, AddOne(29))
|
||||
}
|
||||
|
||||
func TestAddTwo(t *testing.T) {
|
||||
require.Equal(t, 4, AddTwo(2))
|
||||
}
|
12
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/f.go
vendored
Normal file
12
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/f.go
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
// +build !change
|
||||
|
||||
package subpkg
|
||||
|
||||
func AddOne(n int) int {
|
||||
if n == 0 {
|
||||
return 1
|
||||
} else if n == 1 {
|
||||
return 2
|
||||
}
|
||||
return n + 1
|
||||
}
|
13
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/f_test.go
vendored
Normal file
13
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/f_test.go
vendored
Normal file
|
@ -0,0 +1,13 @@
|
|||
package subpkg
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// min coverage: 100%
|
||||
|
||||
func TestAddOne(t *testing.T) {
|
||||
require.Equal(t, 1, AddOne(0))
|
||||
}
|
5
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/g.go
vendored
Normal file
5
tools/testtool/testdata/submissions/correct/coverme/student/coverme/subpkg/g.go
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
package subpkg
|
||||
|
||||
func AddTwo(n int) int {
|
||||
return AddOne(n + 1)
|
||||
}
|
5
tools/testtool/testdata/submissions/correct/coverme/student/go.mod
vendored
Normal file
5
tools/testtool/testdata/submissions/correct/coverme/student/go.mod
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitlab.com/slon/shad-go
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.5.1
|
10
tools/testtool/testdata/submissions/correct/coverme/student/go.sum
vendored
Normal file
10
tools/testtool/testdata/submissions/correct/coverme/student/go.sum
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
77
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/.golangci.yml
vendored
Normal file
77
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/.golangci.yml
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
# options for analysis running
|
||||
run:
|
||||
# default concurrency is a available CPU number
|
||||
concurrency: 8
|
||||
|
||||
# timeout for analysis, e.g. 30s, 5m, default is 1m
|
||||
deadline: 5m
|
||||
|
||||
# exit code when at least one issue was found, default is 1
|
||||
issues-exit-code: 1
|
||||
|
||||
# include test files or not, default is true
|
||||
tests: true
|
||||
|
||||
|
||||
# output configuration options
|
||||
output:
|
||||
# colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number"
|
||||
format: colored-line-number
|
||||
|
||||
# print lines of code with issue, default is true
|
||||
print-issued-lines: true
|
||||
|
||||
# print linter name in the end of issue text, default is true
|
||||
print-linter-name: true
|
||||
|
||||
|
||||
# all available settings of specific linters
|
||||
linters-settings:
|
||||
govet:
|
||||
# report about shadowed variables
|
||||
check-shadowing: true
|
||||
golint:
|
||||
# minimal confidence for issues, default is 0.8
|
||||
min-confidence: 0.8
|
||||
gofmt:
|
||||
# simplify code: gofmt with `-s` option, true by default
|
||||
simplify: true
|
||||
goimports:
|
||||
# put imports beginning with prefix after 3rd-party packages;
|
||||
# it's a comma-separated list of prefixes
|
||||
local-prefixes: gitlab.com
|
||||
|
||||
linters:
|
||||
disable-all: true
|
||||
enable:
|
||||
- errcheck
|
||||
- gofmt
|
||||
- golint
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- scopelint
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unconvert
|
||||
|
||||
|
||||
issues:
|
||||
# List of regexps of issue texts to exclude, empty list by default.
|
||||
# But independently from this option we use default exclude patterns,
|
||||
# it can be disabled by `exclude-use-default: false`. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`
|
||||
exclude:
|
||||
- Using the variable on range scope .* in function literal
|
||||
|
||||
# Independently from option `exclude` we use default exclude patterns,
|
||||
# it can be disabled by this option. To list all
|
||||
# excluded by default patterns execute `golangci-lint run --help`.
|
||||
# Default value for this option is true.
|
||||
exclude-use-default: true
|
||||
|
||||
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
|
||||
max-per-linter: 0
|
||||
|
||||
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
|
||||
max-same-issues: 0
|
5
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/go.mod
vendored
Normal file
5
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/go.mod
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitlab.com/slon/shad-go
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.5.1
|
11
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/go.sum
vendored
Normal file
11
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/go.sum
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
16
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/coverage_test.go
vendored
Normal file
16
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/coverage_test.go
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build !change
|
||||
|
||||
package poorcoverage_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.com/slon/shad-go/poorcoverage"
|
||||
)
|
||||
|
||||
// min coverage: 100%
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), poorcoverage.Sum(1, 1))
|
||||
}
|
10
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/service.go
vendored
Normal file
10
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/service.go
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// +build !change
|
||||
|
||||
package poorcoverage
|
||||
|
||||
func Sum(a, b int64) int64 {
|
||||
if a == 0 {
|
||||
return b
|
||||
}
|
||||
return a + b
|
||||
}
|
14
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/solution_test.go
vendored
Normal file
14
tools/testtool/testdata/submissions/incorrect/poorcoverage/private/poorcoverage/solution_test.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// +build solution
|
||||
|
||||
package poorcoverage
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), Sum(1, 1))
|
||||
require.Equal(t, int64(1), Sum(0, 1))
|
||||
}
|
5
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/go.mod
vendored
Normal file
5
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/go.mod
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
module gitlab.com/slon/shad-go
|
||||
|
||||
go 1.13
|
||||
|
||||
require github.com/stretchr/testify v1.5.1
|
6
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/go.sum
vendored
Normal file
6
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/go.sum
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
16
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/poorcoverage/coverage_test.go
vendored
Normal file
16
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/poorcoverage/coverage_test.go
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
// +build !change
|
||||
|
||||
package poorcoverage_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"gitlab.com/slon/shad-go/poorcoverage"
|
||||
)
|
||||
|
||||
// min coverage: 100%
|
||||
|
||||
func TestSum(t *testing.T) {
|
||||
require.Equal(t, int64(2), poorcoverage.Sum(1, 1))
|
||||
}
|
10
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/poorcoverage/service.go
vendored
Normal file
10
tools/testtool/testdata/submissions/incorrect/poorcoverage/student/poorcoverage/service.go
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// +build !change
|
||||
|
||||
package poorcoverage
|
||||
|
||||
func Sum(a, b int64) int64 {
|
||||
if a == 0 {
|
||||
return b
|
||||
}
|
||||
return a + b
|
||||
}
|
Loading…
Reference in a new issue