summaryrefslogtreecommitdiffstats
path: root/qa/test_commits.py
blob: f485856eadc2cf46adaff97983c44bcf6139a656 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# -*- coding: utf-8 -*-
# pylint: disable=too-many-function-args,unexpected-keyword-arg
import re

import arrow

from qa.shell import echo, git, gitlint
from qa.base import BaseTestCase
from qa.utils import sstr


class CommitsTests(BaseTestCase):
    """ Integration tests for the --commits argument, i.e. linting multiple commits at once or linting specific commits
    """

    def test_successful(self):
        """ Test linting multiple commits without violations """
        git("checkout", "-b", "test-branch-commits-base", _cwd=self.tmp_git_repo)
        self.create_simple_commit(u"Sïmple title\n\nSimple bödy describing the commit")
        git("checkout", "-b", "test-branch-commits", _cwd=self.tmp_git_repo)
        self.create_simple_commit(u"Sïmple title2\n\nSimple bödy describing the commit2")
        self.create_simple_commit(u"Sïmple title3\n\nSimple bödy describing the commit3")
        output = gitlint("--commits", "test-branch-commits-base...test-branch-commits",
                         _cwd=self.tmp_git_repo, _tty_in=True)
        self.assertEqualStdout(output, "")

    def test_violations(self):
        """ Test linting multiple commits with violations """
        git("checkout", "-b", "test-branch-commits-violations-base", _cwd=self.tmp_git_repo)
        self.create_simple_commit(u"Sïmple title.\n")
        git("checkout", "-b", "test-branch-commits-violations", _cwd=self.tmp_git_repo)

        self.create_simple_commit(u"Sïmple title2.\n")
        commit_sha1 = self.get_last_commit_hash()[:10]
        self.create_simple_commit(u"Sïmple title3.\n")
        commit_sha2 = self.get_last_commit_hash()[:10]
        output = gitlint("--commits", "test-branch-commits-violations-base...test-branch-commits-violations",
                         _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[4])

        self.assertEqual(output.exit_code, 4)
        expected_kwargs = {'commit_sha1': commit_sha1, 'commit_sha2': commit_sha2}
        self.assertEqualStdout(output, self.get_expected("test_commits/test_violations_1", expected_kwargs))

    def test_lint_single_commit(self):
        """ Tests `gitlint --commits <sha>` """
        self.create_simple_commit(u"Sïmple title.\n")
        self.create_simple_commit(u"Sïmple title2.\n")
        commit_sha = self.get_last_commit_hash()
        refspec = "{0}^...{0}".format(commit_sha)
        self.create_simple_commit(u"Sïmple title3.\n")
        output = gitlint("--commits", refspec, _cwd=self.tmp_git_repo, _tty_in=True, _ok_code=[2])
        expected = (u"1: T3 Title has trailing punctuation (.): \"Sïmple title2.\"\n" +
                    u"3: B6 Body message is missing\n")
        self.assertEqual(output.exit_code, 2)
        self.assertEqualStdout(output, expected)

    def test_lint_staged_stdin(self):
        """ Tests linting a staged commit. Gitint should lint the passed commit message andfetch additional meta-data
            from the underlying repository. The easiest way to test this is by inspecting `--debug` output.
            This is the equivalent of doing:
            echo "WIP: Pïpe test." | gitlint --staged --debug
        """
        # Create a commit first, before we stage changes. This ensures the repo is properly initialized.
        self.create_simple_commit(u"Sïmple title.\n")

        # Add some files, stage them: they should show up in the debug output as changed file
        filename1 = self.create_file(self.tmp_git_repo)
        git("add", filename1, _cwd=self.tmp_git_repo)
        filename2 = self.create_file(self.tmp_git_repo)
        git("add", filename2, _cwd=self.tmp_git_repo)

        output = gitlint(echo(u"WIP: Pïpe test."), "--staged", "--debug",
                         _cwd=self.tmp_git_repo, _tty_in=False, _err_to_out=True, _ok_code=[3])

        # Determine variable parts of expected output
        expected_kwargs = self.get_debug_vars_last_commit()
        expected_kwargs.update({'changed_files': sstr(sorted([filename1, filename2]))})

        # It's not really possible to determine the "Date: ..." line that is part of the debug output as this date
        # is not taken from git but instead generated by gitlint itself. As a workaround, we extract the date from the
        # gitlint output using a regex, parse the date to ensure the format is correct, and then pass that as an
        # expected variable.
        matches = re.search(r'^Date:\s+(.*)', str(output), re.MULTILINE)
        if matches:
            expected_date = arrow.get(str(matches.group(1)), "YYYY-MM-DD HH:mm:ss Z").format("YYYY-MM-DD HH:mm:ss Z")
            expected_kwargs['staged_date'] = expected_date

        self.assertEqualStdout(output, self.get_expected("test_commits/test_lint_staged_stdin_1", expected_kwargs))
        self.assertEqual(output.exit_code, 3)

    def test_lint_staged_msg_filename(self):
        """ Tests linting a staged commit. Gitint should lint the passed commit message andfetch additional meta-data
            from the underlying repository. The easiest way to test this is by inspecting `--debug` output.
            This is the equivalent of doing:
            gitlint --msg-filename /tmp/my-commit-msg --staged --debug
        """
        # Create a commit first, before we stage changes. This ensures the repo is properly initialized.
        self.create_simple_commit(u"Sïmple title.\n")

        # Add some files, stage them: they should show up in the debug output as changed file
        filename1 = self.create_file(self.tmp_git_repo)
        git("add", filename1, _cwd=self.tmp_git_repo)
        filename2 = self.create_file(self.tmp_git_repo)
        git("add", filename2, _cwd=self.tmp_git_repo)

        tmp_commit_msg_file = self.create_tmpfile(u"WIP: from fïle test.")

        output = gitlint("--msg-filename", tmp_commit_msg_file, "--staged", "--debug",
                         _cwd=self.tmp_git_repo, _tty_in=False, _err_to_out=True, _ok_code=[3])

        # Determine variable parts of expected output
        expected_kwargs = self.get_debug_vars_last_commit()
        expected_kwargs.update({'changed_files': sstr(sorted([filename1, filename2]))})

        # It's not really possible to determine the "Date: ..." line that is part of the debug output as this date
        # is not taken from git but instead generated by gitlint itself. As a workaround, we extract the date from the
        # gitlint output using a regex, parse the date to ensure the format is correct, and then pass that as an
        # expected variable.
        matches = re.search(r'^Date:\s+(.*)', str(output), re.MULTILINE)
        if matches:
            expected_date = arrow.get(str(matches.group(1)), "YYYY-MM-DD HH:mm:ss Z").format("YYYY-MM-DD HH:mm:ss Z")
            expected_kwargs['staged_date'] = expected_date

        expected = self.get_expected("test_commits/test_lint_staged_msg_filename_1", expected_kwargs)
        self.assertEqualStdout(output, expected)
        self.assertEqual(output.exit_code, 3)

    def test_lint_head(self):
        """ Testing whether we can also recognize special refs like 'HEAD' """
        tmp_git_repo = self.create_tmp_git_repo()
        self.create_simple_commit(u"Sïmple title.\n\nSimple bödy describing the commit", git_repo=tmp_git_repo)
        self.create_simple_commit(u"Sïmple title", git_repo=tmp_git_repo)
        self.create_simple_commit(u"WIP: Sïmple title\n\nSimple bödy describing the commit", git_repo=tmp_git_repo)
        output = gitlint("--commits", "HEAD", _cwd=tmp_git_repo, _tty_in=True, _ok_code=[3])
        revlist = git("rev-list", "HEAD", _tty_in=True, _cwd=tmp_git_repo).split()

        expected_kwargs = {"commit_sha0": revlist[0][:10], "commit_sha1": revlist[1][:10],
                           "commit_sha2": revlist[2][:10]}

        self.assertEqualStdout(output, self.get_expected("test_commits/test_lint_head_1", expected_kwargs))

    def test_ignore_commits(self):
        """ Tests multiple commits of which some rules get igonored because of ignore-* rules """
        # Create repo and some commits
        tmp_git_repo = self.create_tmp_git_repo()
        self.create_simple_commit(u"Sïmple title.\n\nSimple bödy describing the commit", git_repo=tmp_git_repo)
        # Normally, this commit will give T3 (trailing-punctuation), T5 (WIP) and B5 (bod-too-short) violations
        # But in this case only B5 because T3 and T5 are being ignored because of config
        self.create_simple_commit(u"Release: WIP tïtle.\n\nShort", git_repo=tmp_git_repo)
        # In the following 2 commits, the T3 violations are as normal
        self.create_simple_commit(
            u"Sïmple WIP title3.\n\nThis is \ta relëase commit\nMore info", git_repo=tmp_git_repo)
        self.create_simple_commit(u"Sïmple title4.\n\nSimple bödy describing the commit4", git_repo=tmp_git_repo)
        revlist = git("rev-list", "HEAD", _tty_in=True, _cwd=tmp_git_repo).split()

        config_path = self.get_sample_path("config/ignore-release-commits")
        output = gitlint("--commits", "HEAD", "--config", config_path, _cwd=tmp_git_repo, _tty_in=True, _ok_code=[4])

        expected_kwargs = {"commit_sha0": revlist[0][:10], "commit_sha1": revlist[1][:10],
                           "commit_sha2": revlist[2][:10], "commit_sha3": revlist[3][:10]}
        self.assertEqualStdout(output, self.get_expected("test_commits/test_ignore_commits_1", expected_kwargs))