mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2025-12-23 22:29:59 -05:00
generate report for api test
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -38,6 +38,9 @@ vendor-php
|
||||
# API acceptance tests - auto-generated files
|
||||
.php-cs-fixer.cache
|
||||
|
||||
# QA activity reports
|
||||
tests/qa-activity-report/reports/
|
||||
|
||||
# drone CI is in .drone.star, do not let someone accidentally commit a local .drone.yml
|
||||
.drone.yml
|
||||
|
||||
|
||||
9
Makefile
9
Makefile
@@ -355,3 +355,12 @@ vendor-bin/php_codesniffer/vendor: vendor/bamarni/composer-bin-plugin vendor-bin
|
||||
|
||||
vendor-bin/php_codesniffer/composer.lock: vendor-bin/php_codesniffer/composer.json
|
||||
@echo php_codesniffer composer.lock is not up to date.
|
||||
|
||||
.PHONY: generate-qa-activity-report
|
||||
generate-qa-activity-report: node_modules
|
||||
@if [ -z "${MONTH}" ] || [ -z "${YEAR}" ]; then \
|
||||
echo "Please set the MONTH and YEAR environment variables. Usage: make generate-qa-activity-report MONTH=<month> YEAR=<year>"; \
|
||||
exit 1; \
|
||||
fi
|
||||
go run tests/qa-activity-report/generate-qa-activity-report.go --month ${MONTH} --year ${YEAR}
|
||||
|
||||
|
||||
225
tests/qa-activity-report/generate-qa-activity-report.go
Normal file
225
tests/qa-activity-report/generate-qa-activity-report.go
Normal file
@@ -0,0 +1,225 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/csv"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
since, until, period, err := getTimeframe()
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
logs, err := getGitLog(since, until)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
csvRows := make([][]string, 0, 1000)
|
||||
|
||||
for _, logLine := range logs {
|
||||
logParts := strings.Split(logLine, " ")
|
||||
if len(logParts) < 2 {
|
||||
continue
|
||||
}
|
||||
|
||||
commit := logParts[0]
|
||||
date := logParts[1]
|
||||
|
||||
diffLines, err := getGitDiff(commit)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
return
|
||||
}
|
||||
|
||||
addedTests, changedTests, deletedTests := 0, 0, 0
|
||||
// var inScenarios bool
|
||||
|
||||
for i, line := range diffLines {
|
||||
switch {
|
||||
case strings.HasPrefix(line, "+") && !strings.HasPrefix(line, "+++"):
|
||||
if strings.Contains(line, "Scenario:") {
|
||||
addedTests++
|
||||
} else if strings.Contains(line, "Scenario Outline:") {
|
||||
addedTests += countAddedTestsInExamples(diffLines, i)
|
||||
}
|
||||
case strings.HasPrefix(line, "-") && !strings.HasPrefix(line, "---"):
|
||||
if strings.Contains(line, "Scenario") {
|
||||
deletedTests++
|
||||
}
|
||||
case strings.Contains(line, "@@ Feature:"):
|
||||
changedTests := 0
|
||||
for i, line := range diffLines {
|
||||
if strings.Contains(line, "@@ Feature:") {
|
||||
inScenarios, changed := checkChangedTests(diffLines, i)
|
||||
if !inScenarios {
|
||||
changedTests += changed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
csvRows = append(csvRows, []string{"API Test", date, strconv.Itoa(addedTests), strconv.Itoa(changedTests), strconv.Itoa(deletedTests), commit})
|
||||
}
|
||||
|
||||
// Ensure the directory exists
|
||||
reportDir := "tests/qa-activity-report/reports"
|
||||
if err := os.MkdirAll(reportDir, os.ModePerm); err != nil {
|
||||
fmt.Println("Error creating directory:", err)
|
||||
return
|
||||
}
|
||||
|
||||
// Define the path for the CSV file
|
||||
filePath := fmt.Sprintf("%s/QA_Activity_Report_%s.csv", reportDir, period)
|
||||
if err := generateCSV(csvRows, filePath); err != nil {
|
||||
fmt.Println("Error writing CSV report:", err)
|
||||
} else {
|
||||
fmt.Println("CSV report generated successfully. You can find it in", filePath)
|
||||
}
|
||||
}
|
||||
|
||||
func getTimeframe() (since string, until string, period string, err error) {
|
||||
monthStr := os.Getenv("MONTH")
|
||||
yearStr := os.Getenv("YEAR")
|
||||
daysStr := os.Getenv("DAYS")
|
||||
|
||||
if monthStr != "" && yearStr != "" {
|
||||
month, err := strconv.Atoi(monthStr)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("invalid month: %w", err)
|
||||
}
|
||||
year, err := strconv.Atoi(yearStr)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("invalid year: %w", err)
|
||||
}
|
||||
startDate := time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
|
||||
endDate := startDate.AddDate(0, 1, -1)
|
||||
since = startDate.Format("2006-01-02")
|
||||
until = endDate.Format("2006-01-02")
|
||||
period = fmt.Sprintf("%02d_%04d", month, year)
|
||||
} else if daysStr != "" {
|
||||
days, err := strconv.Atoi(daysStr)
|
||||
if err != nil {
|
||||
return "", "", "", fmt.Errorf("invalid number of days: %w", err)
|
||||
}
|
||||
until = time.Now().Format("2006-01-02")
|
||||
since = time.Now().AddDate(0, 0, -days).Format("2006-01-02")
|
||||
period = fmt.Sprintf("Last_%d_days", days)
|
||||
} else {
|
||||
return "", "", "", fmt.Errorf("please provide either MONTH and YEAR or DAYS")
|
||||
}
|
||||
|
||||
return since, until, period, nil
|
||||
}
|
||||
|
||||
func getGitLog(since, until string) ([]string, error) {
|
||||
cmd := exec.Command("git", "log", "--since="+since, "--until="+until, "--pretty=format:%H %ad", "--date=short", "--", "tests/acceptance/features", ":(exclude)tests/acceptance/features/bootstrap/")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
if err := cmd.Run(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return strings.Split(out.String(), "\n"), nil
|
||||
}
|
||||
|
||||
func getGitDiff(commit string) ([]string, error) {
|
||||
cmd := exec.Command("git", "diff", commit+"~1", commit, "--", "tests/acceptance/features", ":(exclude)tests/acceptance/features/bootstrap/")
|
||||
var out bytes.Buffer
|
||||
cmd.Stdout = &out
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return strings.Split(out.String(), "\n"), nil
|
||||
}
|
||||
|
||||
func countAddedTestsInExamples(diffLines []string, startIndex int) int {
|
||||
var inExamples bool
|
||||
addedTests := 0
|
||||
|
||||
for j := startIndex + 1; j < len(diffLines); j++ {
|
||||
exampleLine := diffLines[j]
|
||||
if strings.HasPrefix(exampleLine, "+") && strings.Contains(exampleLine, "Examples:") {
|
||||
inExamples = true
|
||||
continue
|
||||
} else if inExamples {
|
||||
trimmedLine := strings.TrimSpace(exampleLine)
|
||||
if strings.HasPrefix(trimmedLine, "+") && strings.Contains(trimmedLine, "|") {
|
||||
// Count a string if it starts with "+" and contains "|"
|
||||
addedTests++
|
||||
} else if strings.TrimSpace(exampleLine) == "" || !strings.HasPrefix(trimmedLine, "+") || !strings.HasPrefix(trimmedLine, "|") {
|
||||
// Abort counting when a row that does not belong to the table is encountered
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We have one line | resource | which is not a test line. So we deleted one line from addedTest
|
||||
// Examples:
|
||||
// | resource |
|
||||
// | testfile.txt |
|
||||
// | FolderToShare |
|
||||
if inExamples {
|
||||
addedTests--
|
||||
}
|
||||
return addedTests
|
||||
}
|
||||
|
||||
func checkChangedTests(diffLines []string, startIndex int) (bool, int) {
|
||||
var inScenarios bool
|
||||
changedTests := 0
|
||||
|
||||
for j := startIndex + 1; j < len(diffLines); j++ {
|
||||
scenarioLine := diffLines[j]
|
||||
if strings.HasPrefix(scenarioLine, "+") || strings.HasPrefix(scenarioLine, "-") {
|
||||
// If there are changes and the string contains the word "Scenario", set inScenarios to true
|
||||
if strings.Contains(scenarioLine, "Scenario") {
|
||||
inScenarios = true
|
||||
break
|
||||
}
|
||||
// If the line no longer starts with "-" "+", then the change block has ended
|
||||
if !strings.HasPrefix(scenarioLine, "-") && !strings.HasPrefix(scenarioLine, "+") {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't find "Scenario" in the changes, increase the changedTests counter
|
||||
if !inScenarios {
|
||||
changedTests++
|
||||
}
|
||||
return inScenarios, changedTests
|
||||
}
|
||||
|
||||
func generateCSV(csvRows [][]string, filePath string) error {
|
||||
file, err := os.Create(filePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
writer := csv.NewWriter(file)
|
||||
defer writer.Flush()
|
||||
|
||||
header := []string{"Test-Type", "Date", "Tests Added", "Tests Changed", "Tests Deleted", "commit-ID"}
|
||||
if err := writer.Write(header); err != nil {
|
||||
return err
|
||||
}
|
||||
for _, row := range csvRows {
|
||||
if err := writer.Write(row); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user