blob: 8d5f69215fa59133488fbfbf2d35f837526c7fb0 [file] [log] [blame]
Oleksii Petrenko99539bd2020-07-31 20:00:06 +03001import datetime
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +03002import json
3import os
Sofiia Andriichenko4b440da2023-02-10 12:29:46 +01004from .celery_tasks import test_rail_api
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +03005
6from django.shortcuts import render, redirect, HttpResponse
Anna Arhipova22ea6bf2024-02-20 15:25:30 +01007from django_celery_beat.models import CrontabSchedule, PeriodicTasks
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +03008
9from . import models
10from . import forms
Anna Arhipova7cdcc852023-11-15 18:20:45 +010011from .celery_tasks.tasks import process_run, update_plot_data, \
12 get_test_passability_in_suite
13from .utils import short_names_for_dict, get_dict_diff
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030014
15
16def index(request):
Oleksii Petrenko68268172020-09-28 16:58:13 +030017 runs = models.TestRailTestRun.objects.all()
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030018 return render(request, "control/index.html", {"runs": runs})
19
20
21def redirect_to_index(request):
22 return redirect("index")
23
24
25def single_run(request, run_id):
Oleksii Petrenko68268172020-09-28 16:58:13 +030026 run = models.TestRailTestRun.objects.get(pk=run_id)
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030027 if request.method == "POST":
28 form = forms.TestRunForm(request.POST, instance=run)
29 if form.is_valid():
30 form.save()
31 return redirect("single_run", run_id)
32 else:
33 form = forms.TestRunForm(instance=run)
34
35 return render(request, "control/update_run.html",
Anna Arhipovae9258f32023-11-04 12:31:19 +010036 {"form": form, "run_id": run_id, "checked_tests":
37 run.checked_tests})
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030038
39
40def create_run(request):
41 if request.method == "POST":
42 form = forms.TestRunForm(request.POST)
43 if form.is_valid():
44 obj = form.save()
45 return redirect("single_run", obj.id)
46 else:
47 form = forms.TestRunForm()
48
Anna Arhipova62760612023-11-28 23:20:38 +010049 form.fields["created_after"].initial = datetime.date.today() + \
50 datetime.timedelta(days=-3 * 30)
51 form.fields["created_before"].initial = datetime.date.today()
Anna Arhipova175d4712023-11-06 11:19:44 +010052 return render(request, "control/update_run.html", {"form": form})
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030053
54
55def list_reports(request):
Oleksii Petrenko68268172020-09-28 16:58:13 +030056 reports = models.TestRailReport.objects.order_by("-created_at").all()
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030057 return render(request, "control/reports.html", {"reports": reports})
58
59
60def single_report(request, report_id):
Oleksii Petrenko68268172020-09-28 16:58:13 +030061 report = models.TestRailReport.objects.get(pk=report_id)
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030062 data = report.path.read().decode("utf-8")
Anna Arhipova7cdcc852023-11-15 18:20:45 +010063 if request.method == "POST" \
64 and request.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest':
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030065 return HttpResponse(
66 json.dumps({"data": data, "finished": report.finished}),
67 content_type="application/json")
Anna Arhipova175d4712023-11-06 11:19:44 +010068
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030069 return render(request, "control/report.html",
Anna Arhipova175d4712023-11-06 11:19:44 +010070 {"report_id": report.id,
71 "report": data,
72 "finished": report.finished})
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030073
74
Anna Arhipova6ecdd342023-11-21 13:43:37 +010075def delete_report(request, report_id):
76 report:models.TestRailReport = models.TestRailReport.objects.get(pk=report_id)
77 try:
78 os.remove(report.path.path)
79 except FileNotFoundError:
80 pass
81 report.delete()
82 return redirect("list_reports")
83
84
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +030085def submit_run(request, run_id):
Oleksii Petrenko68268172020-09-28 16:58:13 +030086 run = models.TestRailTestRun.objects.get(pk=run_id)
Anna Arhipovae9258f32023-11-04 12:31:19 +010087 is_testplan = test_rail_api.is_testplan(run.run_id)
Anna Arhipovae9258f32023-11-04 12:31:19 +010088 if is_testplan:
89 testrail_run = test_rail_api.get_plan_by_id(run.run_id)
90 else:
91 testrail_run = test_rail_api.get_run_by_id(run.run_id)
Sofiia Andriichenko4b440da2023-02-10 12:29:46 +010092 if not run.run_name:
Anna Arhipovaf1ea3ee2024-01-24 13:29:09 +010093 if is_testplan:
94 _name = f"Plan {testrail_run['name']}"
95 else:
96 parent_plan_id = testrail_run["plan_id"]
97 parent_plan_name = \
98 test_rail_api.get_plan_by_id(parent_plan_id)["name"]
99 _name = f"Run {testrail_run['name']} from {parent_plan_name}"
100 run.run_name = _name
101 run.save()
102
Sofiia Andriichenko4b440da2023-02-10 12:29:46 +0100103 report_name = "{}-run_id-{}-date-{}".format(
Anna Arhipovaf1ea3ee2024-01-24 13:29:09 +0100104 run.run_name,
105 run.run_id,
106 datetime.datetime.isoformat(datetime.datetime.now()))
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +0300107 path = os.path.join(models.fs.location, report_name)
108 with open(path, "w"):
109 pass
110
Oleksii Petrenko68268172020-09-28 16:58:13 +0300111 report = models.TestRailReport(
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +0300112 report_name=report_name,
113 path=path)
114 report.save()
Anna Arhipovae9258f32023-11-04 12:31:19 +0100115 process_run.delay(run_id, report.id, path, is_testplan)
Oleksii Petrenko12508832020-07-10 18:13:53 +0300116 return redirect("single_report", report.id)
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +0300117
118
Anna Arhipova52cdec92023-10-05 23:05:48 +0200119def delete_run(request, run_id):
120 run = models.TestRailTestRun.objects.get(pk=run_id)
121 run.delete()
122 return redirect("index")
123
124
Oleksii Petrenko24f1f8f2020-06-26 18:09:43 +0300125def show_help(request):
126 return render(request, "control/help.html")
Oleksii Petrenko68268172020-09-28 16:58:13 +0300127
128
129def update_jenkins_plot(request):
130 try:
131 models.ActionLog.objects.get(name="update_plot_started")
132 return HttpResponse("Update in progress", status=403)
133 except models.ActionLog.DoesNotExist:
134 pass
135 update = models.ActionLog(
136 name="update_plot_started", date=datetime.datetime.now())
137 update.save()
138 update_plot_data.delay()
139 return HttpResponse("Started Update", status=200)
140
141
142def jenkins_plot(request):
143 try:
144 update_date = models.ActionLog.objects.get(
145 name="update_jenkins_plot").date
146 except models.ActionLog.DoesNotExist:
147 update_date = None
148 try:
149 models.ActionLog.objects.get(name="update_plot_started")
150 update_started = True
151 except models.ActionLog.DoesNotExist:
152 update_started = False
153
154 job_names_path = os.path.join(models.fs.location, "job_names.txt")
155 job_names = []
156 if os.path.exists(job_names_path):
157 try:
158 with open(job_names_path, "r") as f:
159 job_names = json.load(f)
160 except:
161 pass
162
163 return render(
164 request, "control/jenkins_plot.html",
165 {"update_date": update_date, "update_started": update_started,
166 "job_names": enumerate(job_names, 1)})
Anna Arhipova7cdcc852023-11-15 18:20:45 +0100167
168
169def submit_suites(request):
170 form = forms.DiffPassRatesForm(request.POST)
171 if not form.is_valid():
172 print(f"{form.errors=}")
173 return
174 report1 = models.SuitePassRate(suite_id=request.POST["first-suite_id"])
175 report1.save()
176 report2 = models.SuitePassRate(suite_id=request.POST["second-suite_id"])
177 report2.save()
178
179 diff_model = models.DiffOfSuitesPassRates(
180 report1=report1,
181 report2=report2,
182 limit=form.cleaned_data["limit"],
183 test_keyword=form.cleaned_data["test_keyword"]
184 )
185 diff_model.save()
186 get_test_passability_in_suite.delay(diff_model.id, report1.id)
187 get_test_passability_in_suite.delay(diff_model.id, report2.id)
188
189 return redirect("report_comparing_suites", diff_model.id)
190
191
192def compare_suites(request):
193 if request.method == "POST":
194 return submit_suites(request)
195
196 diff_form = forms.DiffPassRatesForm()
197 report1_form = forms.SuitePassRateForm(prefix='first')
198 report2_form = forms.SuitePassRateForm(prefix='second')
199
200 return render(
201 request, "control/compare_suites.html",
202 {
203 "diff_form": diff_form,
204 "report1_form": report1_form,
205 "report2_form": report2_form,
206 "finished": None
207 })
208
209
210def list_of_comparing_reports(request):
211 list_of_reports = models.DiffOfSuitesPassRates.objects.all()
212 return render(
213 request, "control/list_comparing_suites.html",
214 {
215 "reports": list_of_reports
216 })
217
218
219def report_comparing_suites(request, report_id):
220 report = models.DiffOfSuitesPassRates.objects.get(pk=report_id)
221 passrate1 = short_names_for_dict(json.loads(
222 report.report1.passrate_by_tests))
223 passrate2 = short_names_for_dict(json.loads(
224 report.report2.passrate_by_tests))
225
226 diff_table = get_dict_diff(dict1=passrate1,
227 dict2=passrate2,
228 compare_by_key="rate")
229 diff_form = forms.DiffPassRatesForm(instance=report)
230 report1_form = forms.SuitePassRateForm(instance=report.report1,
231 prefix="first")
232 report2_form = forms.SuitePassRateForm(instance=report.report2,
233 prefix="second")
234
235 return render(
236 request, "control/compare_suites.html",
237 {"diff_form": diff_form,
238 "report1_form": report1_form,
239 "report2_form": report2_form,
240 "report1": report.report1,
241 "report2": report.report2,
242 "is_finished": report.report1.finished and report.report2.finished,
243 "diff_table": diff_table})
Anna Arhipova22ea6bf2024-02-20 15:25:30 +0100244
245
246def schedulers(request):
247
248 return render(
249 request, "control/schedulers.html",
250 {"schedulers": models.CronPeriodicTask.objects.all()})
251
252
253def scheduler(request, pk=None):
254 if request.method == "POST":
255 return save_scheduler(request)
256
257 if pk:
258 task_pk = models.CronPeriodicTask.objects.get(pk=pk)
259 form = forms.PeriodicTaskForm(instance=task_pk)
260 else:
261 form = forms.PeriodicTaskForm()
262
263 return render(
264 request, "control/scheduler.html",
265 {
266 "form": form,
267 "pk": pk,
268 "TASK_CHOICES": models.TASK_CHOICES
269 }
270 )
271
272
273def save_scheduler(request, pk=None):
274 minute, hour, day_of_month, month_of_year, day_of_week = \
275 request.POST.get("cron", "* * * * *").split(" ")
276 if pk is None:
277 sch = CrontabSchedule.objects.create(
278 minute=minute,
279 hour=hour,
280 day_of_month=day_of_month,
281 month_of_year=month_of_year,
282 day_of_week=day_of_week
283 )
284 task = models.CronPeriodicTask.objects.create(
285 crontab=sch,
286 cron=request.POST.get("cron"),
287 name=request.POST.get("name"),
288 task="control.celery_tasks.tasks.check_today_testplan",
289 enabled=request.POST.get("enabled") == 'on',
290 # TODO(harhipova): uncomment when implemented tasks with arguments
291 # args=args,
292 # kwargs=kwargs,
293 )
294 else:
295 task = models.CronPeriodicTask.objects.get(pk=pk)
296 form = forms.PeriodicTaskForm(request.POST, instance=task)
297 CrontabSchedule.objects.filter(id=task.crontab.id).update(
298 minute=minute,
299 hour=hour,
300 day_of_month=day_of_month,
301 month_of_year=month_of_year,
302 day_of_week=day_of_week
303 )
304 form.save()
305 PeriodicTasks.update_changed()
306 return render(
307 request, "control/scheduler.html",
308 {
309 "form": form,
310 "pk": task.id,
311 "TASK_CHOICES": models.TASK_CHOICES
312 }
313 )
314
315
316def delete_scheduler(request, pk):
317 task = models.CronPeriodicTask.objects.get(pk=pk)
318 task.delete()
319 return redirect("schedulers")