class Project(models.Model):
    name = models.CharField(_('Name'), max_length=128, unique=True)

    def __str__(self):
        return 'Project: {0}'.format(self.name) class Settings(models.Model):
    project = models.ForeignKey(Project, related_name='settings')
    key = models.CharField(max_length=255)
    value = models.TextField()

    def __str__(self):
        return "{}={}".format(self.key, self.value) class TestPlan(models.Model):
    name = models.CharField(_('Name'), max_length=256)
    project = models.ForeignKey(Project)
    main = models.BooleanField(_('Show in short statistic'),
                               blank=True, null=False, default=False)
    hidden = models.BooleanField(blank=False, null=False, default=True)
    owner = models.ForeignKey(User, default=1)
    filter = models.TextField(_('Started by filter'), default='',
                              blank=True, null=False, max_length=128)
    description = models.TextField(_('Description'), default='',
                                   blank=True, null=False)
    variable_name = models.TextField(_('Environment variable name'),
                                     default='', blank=True,
                                     null=False, max_length=128)
    variable_value_regexp = models.CharField(_('Regexp for variable value'),
                                             max_length=255, default='',
                                             blank=True)
    show_in_summary = models.BooleanField(
        _('Consider in summary calculation'),
        blank=True, null=False, default=False)

    show_in_twodays = models.BooleanField(
        _('Consider in statistic for last two days'),
        blank=True, null=False, default=False)

    def __str__(self):
        return '{0} -> TestPlan: {1}'.format(self.project, self.name) class Launch(models.Model):
    test_plan = models.ForeignKey(TestPlan)
    counts_cache = models.TextField(blank=True, null=True, default=None)
    started_by = models.URLField(_('Started by'), blank=True, null=True,
                                 default=None)
    created = models.DateTimeField(_('Created'), auto_now_add=True)
    finished = models.DateTimeField(_('Finished'), default=None, blank=True,
                                    null=True)
    state = models.IntegerField(_('State'), default=FINISHED)
    tasks = models.TextField(_('Tasks'), default='')
    parameters = models.TextField(_('Parameters'), default='{}')
    duration = models.FloatField(_('Duration time'), null=True, default=None)

    def is_finished(self):
        return self.state == FINISHED

    @property
    def counts(self):
        if self.counts_cache is None or self.state == INITIALIZED:
            self.calculate_counts()
        return json.loads(self.counts_cache)

    def calculate_counts(self):
        data = {
            'passed': len(self.passed),
            'failed': len(self.failed),
            'skipped': len(self.skipped),
            'blocked': len(self.blocked),
            'total': 0
        }
        for name, count in data.items():
            if name != 'total':
                data['total'] += count
        self.counts_cache = json.dumps(data)
        self.save()

    @property
    def failed(self):
        return self.testresult_set.filter(state=FAILED)

    @property
    def skipped(self):
        return self.testresult_set.filter(state=SKIPPED)

    @property
    def passed(self):
        return self.testresult_set.filter(state=PASSED)

    @property
    def blocked(self):
        return self.testresult_set.filter(state=BLOCKED)

    def get_tasks(self):
        if self.tasks == '' or self.tasks is None:
            self.tasks = '{}'
        return json.loads(self.tasks)

    def set_tasks(self, tasks):
        self.tasks = json.dumps(tasks)

    def get_parameters(self):
        if self.parameters == '' or self.parameters is None:
            self.parameters = '{}'
        return json.loads(self.parameters)

    def set_parameters(self, parameters):
        self.parameters = json.dumps(parameters)

    def __str__(self):
        return '{0} -> Launch: {1}'.format(self.test_plan, self.pk) class Build(models.Model):
    launch = models.OneToOneField(Launch, related_name='build')
    version = models.CharField(
        max_length=16, default=None, null=True, blank=True)
    hash = models.CharField(
        max_length=64, default=None, null=True, blank=True)
    branch = models.CharField(
        max_length=128, default=None, null=True, blank=True)
    commit_author = models.CharField(
        max_length=16, default=None, null=True, blank=True)
    commit_message = models.CharField(
        max_length=128, default=None, null=True, blank=True)
    last_commits = models.TextField(default=None, null=True, blank=True)

    def get_last_commits(self):
        if self.last_commits == '""' or self.last_commits is None:
            self.last_commits = '[]'
        return json.loads(self.last_commits)

    def set_last_commits(self, last_commits):
        self.last_commits = json.dumps(last_commits)

    def __str__(self):
        return '{0} -> LaunchBuild: {1}/{2}/{3}'.format(
            self.launch, self.version, self.hash, self. branch) class Bug(models.Model):
    externalId = models.CharField(max_length=255, blank=False)
    name = models.CharField(max_length=255, default='', blank=True)
    regexp = models.CharField(max_length=255, default='', blank=False)
    state = models.CharField(max_length=32, default='', blank=True)
    updated = models.DateTimeField(auto_now=True)

    def get_state(self):
        return self.state

    def __str__(self):
        return ':'.join((self.externalId, self.name)) TEST_STATES = (PASSED, FAILED, SKIPPED, BLOCKED) = (0, 1, 2, 3)
LAUNCH_STATES = (INITIALIZED, IN_PROGRESS, FINISHED, STOPPED) = (0, 1, 2, 3)
LAUNCH_TYPES = (ASYNC_CALL, INIT_SCRIPT, CONCLUSIVE) = (0, 1, 2)
CELERY_FINISHED_STATES = (states.SUCCESS, states.FAILURE)
RESULT_PREVIEW_CHOICES = (
    ('head', 'Show test result head'),
    ('tail', 'Show test result tail')
)
class ExtUser(models.Model):
class TestPlan(models.Model):
class Launch(models.Model):
class Build(models.Model):
class TestResult(models.Model):
class LaunchItem(models.Model):
class Bug(models.Model):
    def get_dashboards(self):
    def set_dashboards(self, dashboards):
    def __str__(self):
    def is_finished(self):
    def counts(self):
    def calculate_counts(self):
    def failed(self):
    def skipped(self):
    def passed(self):
    def blocked(self):
    def get_tasks(self):
    def set_tasks(self, tasks):
    def get_parameters(self):
    def set_parameters(self, parameters):
    def __str__(self):
    def get_last_commits(self):
    def set_last_commits(self, last_commits):
    def __str__(self):
    def __str__(self):
    def __str__(self):
    def get_state(self):
    def __str__(self):
def get_issue_fields_from_bts(externalId):
def _get_bug(bug_id): TEST_STATES = (PASSED, FAILED, SKIPPED, BLOCKED) = (0, 1, 2, 3)
LAUNCH_STATES = (INITIALIZED, IN_PROGRESS, FINISHED, STOPPED) = (0, 1, 2, 3)
LAUNCH_TYPES = (ASYNC_CALL, INIT_SCRIPT, CONCLUSIVE) = (0, 1, 2)
CELERY_FINISHED_STATES = (states.SUCCESS, states.FAILURE)
RESULT_PREVIEW_CHOICES = (
    ('head', 'Show test result head'),
    ('tail', 'Show test result tail')
)
class ExtUser(models.Model):
class TestPlan(models.Model):
class Launch(models.Model):
class Build(models.Model):
class TestResult(models.Model):
class LaunchItem(models.Model):
class Bug(models.Model):
    def get_dashboards(self):
    def set_dashboards(self, dashboards):
    def __str__(self):
    def is_finished(self):
    def counts(self):
    def calculate_counts(self):
    def failed(self):
    def skipped(self):
    def passed(self):
    def blocked(self):
    def get_tasks(self):
    def set_tasks(self, tasks):
    def get_parameters(self):
    def set_parameters(self, parameters):
    def __str__(self):
    def get_last_commits(self):
    def set_last_commits(self, last_commits):
    def __str__(self):
    def __str__(self):
    def __str__(self):
    def get_state(self):
    def __str__(self):
def get_issue_fields_from_bts(externalId):
def _get_bug(bug_id): TEST_STATES = (PASSED, FAILED, SKIPPED, BLOCKED) = (0, 1, 2, 3)
LAUNCH_STATES = (INITIALIZED, IN_PROGRESS, FINISHED, STOPPED) = (0, 1, 2, 3)
LAUNCH_TYPES = (ASYNC_CALL, INIT_SCRIPT, CONCLUSIVE) = (0, 1, 2)
CELERY_FINISHED_STATES = (states.SUCCESS, states.FAILURE)
RESULT_PREVIEW_CHOICES = (
    ('head', 'Show test result head'),
    ('tail', 'Show test result tail')
)
class ExtUser(models.Model):
class TestPlan(models.Model):
class Launch(models.Model):
class Build(models.Model):
class TestResult(models.Model):
class LaunchItem(models.Model):
class Bug(models.Model):
    def get_dashboards(self):
    def set_dashboards(self, dashboards):
    def __str__(self):
    def is_finished(self):
    def counts(self):
    def calculate_counts(self):
    def failed(self):
    def skipped(self):
    def passed(self):
    def blocked(self):
    def get_tasks(self):
    def set_tasks(self, tasks):
    def get_parameters(self):
    def set_parameters(self, parameters):
    def __str__(self):
    def get_last_commits(self):
    def set_last_commits(self, last_commits):
    def __str__(self):
    def __str__(self):
    def __str__(self):
    def get_state(self):
    def __str__(self):
def get_issue_fields_from_bts(externalId):
def _get_bug(bug_id): class Stage(models.Model):
    name = models.CharField(max_length=128)
    project = models.ForeignKey(Project)
    text = models.TextField(default='', blank=True)
    link = models.URLField(default=None, blank=True, null=True)
    state = models.CharField(max_length=24, default='info', blank=True)
    weight = models.IntegerField(default=0)
    updated = models.DateTimeField(default=datetime.datetime.now())

    def save(self, *args, **kwargs):
        self.updated = datetime.datetime.now()
        return super(Stage, self).save(*args, **kwargs)

    def __str__(self):
        return self.name class Metric(models.Model):
    project = models.ForeignKey(Project)
    name = models.CharField(max_length=128)
    query = models.TextField(default='', blank=True)
    schedule = models.ForeignKey(PeriodicTask)
    handler = models.CharField(max_length=128, choices=HANDLER_CHOICES)
    error = models.TextField(default='', blank=True)
    weight = models.IntegerField(default=1)

    def __str__(self):
        return '{} -> Metric: {}'.format(self.project, self.name)

    def get_schedule_as_cron(self):
        cron = self.schedule.crontab
        return '{} {} {} {} {}'.format(cron.minute, cron.hour,
                                       cron.day_of_month, cron.month_of_year,
                                       cron.day_of_week) class MetricValue(models.Model):
    metric = models.ForeignKey(Metric)
    value = models.FloatField(default=None,
                              validators=[MinValueValidator(0.0)])
    created = models.DateTimeField()

    def __str__(self):
        return self.value

    def save(self, force_insert=False, force_update=False, using=None,
             update_fields=None):
        if self.created is None:
            self.created = timezone.now()
        super().save(force_insert, force_update, using, update_fields) @celery.task()
def update_bugs():
    if settings.JIRA_INTEGRATION:
        for bug in Bug.objects.all():
            try:
                update_state(bug)
            except Exception as e:
                log.error('Unable to update bug {}: {}'.
                          format(bug.externalId, e))
    else:
        log.info('Jira integration is off. '
                 'If you want to use this feature, turn it on.') @celery.task()
def cleanup_database():
    days = timezone.now().date() - timedelta(
        days=settings.STORE_TESTRESULTS_IN_DAYS)

    list(map(lambda launch: launch.testresult_set.all().delete(),
         Launch.objects.filter(finished__lte=days)))
from django.test import TestCase
from django.conf import settings
from django.contrib.auth.models import User, Permission, ContentType
from common.models import Project, Settings
from testreport.models import TestPlan
from testreport.models import Launch
from testreport.models import Build
from testreport.models import Bug
from testreport.models import INIT_SCRIPT, ASYNC_CALL
from testreport.models import PASSED, FAILED, SKIPPED, BLOCKED
from testreport.models import STOPPED
from stages.models import Stage
from metrics.models import Metric, MetricValue
from djcelery.models import PeriodicTask, CrontabSchedule
from testreport.tasks import update_bugs
from testreport.tasks import cleanup_database
from django.test.utils import override_settings
from django.utils import timezone
from datetime import timedelta
from datetime import datetime
import requests_mock
import json
import random
import os
import base64
                   url='{}/junit/junit.xml'.format(testplan.id))

        launches = self._call_rest('get',
                                   'launches/?testplan={}'.format(testplan.id))
        self.assertEqual(1, launches['count'])
        launch = launches['results'][0]
        failed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], FAILED))
        blocked = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], BLOCKED))
        skipped = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], SKIPPED))
        passed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], PASSED))
        self.assertEqual(1, failed['count'])
        self.assertEqual(1, blocked['count'])
        self.assertEqual(
            'Failure message',
            failed['results'][0]['failure_reason'])
        self.assertEqual(
            'Error messageSystem-out',
            blocked['results'][0]['failure_reason'])
        self.assertEqual(1, skipped['count'])
        self.assertEqual(1, passed['count'])
        self.assertEqual(0.4, launch['duration'])

    def test_upload_junit_file_notime(self):
        project = Project.objects.create(name='DummyTestProject')
        testplan = TestPlan.objects.create(name='DummyTestPlan',
                                           project=project)
        self._post(file_name='junit-test-report-notime.xml',
                   url='{}/junit/junit.xml'.format(testplan.id))

        launches = self._call_rest('get',
                                   'launches/?testplan={}'.format(testplan.id))
        self.assertEqual(1, launches['count'])
        launch = launches['results'][0]
        self.assertEqual(0.0, launch['duration'])

    def test_upload_nunit_file(self):
        project = Project.objects.create(name='DummyTestProject')
        testplan = TestPlan.objects.create(name='DummyTestPlan',
                                           project=project)
        self._post(file_name='nunit-test-report.xml',
                   url='{}/nunit/nunit.xml'.format(testplan.id))

        launches = self._call_rest('get',
                                   'launches/?testplan={}'.format(testplan.id))
        self.assertEqual(1, launches['count'])
        launch = launches['results'][0]
        failed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], FAILED))
        skipped = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], SKIPPED))
        passed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], PASSED))
        self.assertEqual(1, failed['count'])
        self.assertEqual(1, skipped['count'])
        self.assertEqual(1, passed['count'])
        self.assertEqual(0.2, launch['duration'])

    def test_upload_qttestxunit_file(self):
        failed_failure_reason = \
            'Error message\n\nLogs:\n     error log lines \n    \n  '
        skipped_failure_reason = \
            '\n     message="skip reason" type="skip" \n  '

        project = Project.objects.create(name='DummyTestProject')
        testplan = TestPlan.objects.create(name='DummyTestPlan',
                                           project=project)
        self._post(file_name='qttestxunit-test-report.xml',
                   url='{}/qttestxunit/xunit.xml'.format(testplan.id))

        launches = self._call_rest('get',
                                   'launches/?testplan={}'.format(testplan.id))
        self.assertEqual(1, launches['count'])
        launch = launches['results'][0]
        failed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], FAILED))
        skipped = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], SKIPPED))
        passed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], PASSED))
        self.assertEqual(1, failed['count'])
        self.assertEqual(failed_failure_reason,
                         failed["results"][0]["failure_reason"])
        self.assertEqual(1, skipped['count'])
        self.assertEqual(skipped_failure_reason,
                         skipped["results"][0]["failure_reason"])
        self.assertEqual(1, passed['count'])
        self.assertEqual(0, launch['duration'])

    def test_upload_xcprettyjunit_file(self):
        failed_failure_reason = 'file_name.swift:94\n\nFailure message'

        project = Project.objects.create(name='DummyTestProject')
        testplan = TestPlan.objects.create(name='DummyTestPlan',
                                           project=project)
        self._post(file_name='xcprettyjunit-test-report.xml',
                   url='{}/xcprettyjunit/xunit.xml'.format(testplan.id))

        launches = self._call_rest('get',
                                   'launches/?testplan={}'.format(testplan.id))
        self.assertEqual(1, launches['count'])
        launch = launches['results'][0]
        failed = self._call_rest(
            'get',
            'testresults/?launch={}&state={}'.format(launch['id'], FAILED))
        skipped = self._call_rest(
            'get',

            'testresults/?launch={}&state={}'.format(launch['id'], SKIPPED))