Skip to content

Commit fc82a19

Browse files
author
Jakub Ruzicka
committed
Add BDD feature tests using python-behave
Introduce behavioral tests for rdopkg patch and new-version that should from now on be used for description of high level behavior while unit tests should only cover individual functions. Introduce new rdopkg.utils.distgitmagic module with shared code for sample distgit creation and testing. Cleanup hook leaves test dir untouched for failed tests. Run behave To get verbose colorful output. Fixes: #123 Change-Id: I56c642796d849f7452f1abad67613c1a4d0b1563
1 parent 52c3978 commit fc82a19

File tree

8 files changed

+308
-3
lines changed

8 files changed

+308
-3
lines changed

features/environment.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# -*- coding: UTF-8 -*-
2+
import os
3+
import shutil
4+
5+
6+
def clean_tempdir(context, scenario):
7+
"""
8+
Clean up temporary test dirs for passed tests.
9+
10+
Leave failed test dirs for manual inspection.
11+
12+
"""
13+
tempdir = getattr(context, 'tempdir', None)
14+
if tempdir and scenario.status == 'passed':
15+
shutil.rmtree(tempdir)
16+
del(context.tempdir)
17+
18+
19+
def restore_cwd(context):
20+
"""
21+
Return to original working dir or behave gets confused :-/
22+
"""
23+
old_cwd = getattr(context, 'old_cwd', None)
24+
if old_cwd:
25+
os.chdir(old_cwd)
26+
27+
28+
def after_scenario(context, scenario):
29+
clean_tempdir(context, scenario)
30+
restore_cwd(context)

features/newversion.feature

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
Feature: rdopkg new-version
2+
Updating package to new version is a core feature
3+
4+
Scenario: rdopkg new-version --bump-only
5+
Given a distgit at Version 2.0.0 and Release 3
6+
When I run rdopkg new-version --bump-only -n 2.1.0
7+
Then .spec file tag Version is 2.1.0
8+
Then .spec file tag Release is 1%{?dist}
9+
Then .spec file doesn't contain patches_base
10+
Then .spec file contains new changelog entry with 1 lines
11+
Then new commit was created
12+
13+
Scenario: rdopkg new-version with upstream patches
14+
Given a distgit at Version 0.1 and Release 0.1
15+
Given a patches branch with 5 patches
16+
Given a new version 1.0.0 with 2 patches from patches branch
17+
When I run rdopkg new-version -lntU 1.0.0
18+
Then .spec file tag Version is 1.0.0
19+
Then .spec file tag Release is 1%{?dist}
20+
Then .spec file doesn't contain patches_base
21+
Then .spec file has 3 patches defined
22+
Then .spec file contains new changelog entry with 1 lines
23+
Then new commit was created

features/patch.feature

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Feature: rdopkg patch
2+
Updating patches from patches branch is a core feature
3+
4+
Scenario: rdopkg patch
5+
Given a distgit
6+
Given a patches branch with 5 patches
7+
When I run rdopkg patch -l
8+
Then .spec file has 5 patches defined
9+
Then .spec file doesn't contain patches_base
10+
Then .spec file contains new changelog entry with 5 lines
11+
Then new commit was created
12+
13+
Scenario: rdopkg patch --no-bump
14+
Given a distgit
15+
Given a patches branch with 3 patches
16+
When I run rdopkg patch --no-bump -l
17+
Then .spec file has 3 patches defined
18+
Then .spec file doesn't contain patches_base
19+
Then .spec file doesn't contain new changelog entries
20+
Then new commit was created

features/steps/distgit.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
from behave import *
2+
import os
3+
4+
from rdopkg.utils import distgitmagic
5+
from rdopkg.utils import specfile
6+
from rdopkg.utils.distgitmagic import git, run
7+
8+
9+
@given('a distgit at Version {version} and Release {release}')
10+
def step_impl(context, version, release):
11+
name = 'foo-bar'
12+
context.execute_steps(u'Given a temporary directory')
13+
context.distgitdir = distgitmagic.create_sample_distgit(
14+
name, version=version, release=release)
15+
os.chdir(context.distgitdir)
16+
# collect .spec state to compare against after actions
17+
spec = specfile.Spec()
18+
context.old_changelog_entry = spec.get_last_changelog_entry()
19+
context.old_commit = git.current_commit()
20+
21+
22+
@given('a distgit')
23+
def step_impl(context):
24+
context.execute_steps(u'Given a distgit at Version 1.2.3 and Release 2')
25+
26+
27+
@given('a patches branch with {n:n} patches')
28+
def step_impl(context, n):
29+
distgitmagic.create_sample_patches_branch(n)
30+
31+
32+
@given('a new version {version} with {n:n} patches from patches branch')
33+
def step_impl(context, version, n):
34+
distgitmagic.create_sample_upstream_new_version(version, 9, n)
35+
36+
37+
@given('a new version {version}')
38+
def step_impl(context, version):
39+
context.execute_steps(
40+
u'Given a new version %s with 0 patches from patches branch' %
41+
version)
42+
43+
44+
@then('.spec file tag {tag} is {value}')
45+
def step_impl(context, tag, value):
46+
spec = specfile.Spec()
47+
assert spec.get_tag(tag) == value
48+
49+
50+
@then('.spec file contains new changelog entry with {n:n} lines')
51+
def step_impl(context, n):
52+
spec = specfile.Spec()
53+
entry = spec.get_last_changelog_entry()
54+
assert len(entry[1]) == n
55+
assert entry != context.old_changelog_entry
56+
57+
58+
@then('.spec file doesn\'t contain new changelog entries')
59+
def step_impl(context):
60+
entry = specfile.Spec().get_last_changelog_entry()
61+
assert entry == context.old_changelog_entry
62+
63+
64+
@then('.spec file has {n:n} patches defined')
65+
def step_impl(context, n):
66+
spec = specfile.Spec()
67+
assert spec.get_n_patches() == n
68+
69+
70+
@then('.spec file doesn\'t contain patches_base')
71+
def step_impl(context):
72+
spec = specfile.Spec()
73+
assert spec.get_patches_base() == (None, 0)
74+
75+
76+
@then('new commit was created')
77+
def step_impl(context):
78+
new_commit = git.current_commit()
79+
assert new_commit != context.old_commit

features/steps/utils.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from behave import *
2+
import os
3+
import tempfile
4+
5+
from rdopkg.utils.distgitmagic import run
6+
7+
8+
@when('I run rdopkg {args}')
9+
def step_impl(context, args):
10+
# proper argument parsing might be needed
11+
cmd = ['rdopkg'] + args.split(' ')
12+
run(*cmd)
13+
14+
15+
@given('a temporary directory')
16+
def step_impl(context):
17+
context.tempdir = tempfile.mkdtemp(prefix='rdopkg-test-')
18+
context.old_cwd = os.getcwd()
19+
os.chdir(context.tempdir)

rdopkg/utils/distgitmagic.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
import os
2+
from rdopkg import helpers
3+
import rdopkg.utils.cmd
4+
from rdopkg.utils import specfile
5+
6+
7+
SAMPLE_SPEC = u"""
8+
Name: {name}
9+
Epoch: 1
10+
Version: {version}
11+
Release: {release}%{{?dist}}
12+
Summary: Amazing {name} package
13+
14+
Group: Development/Languages
15+
License: ASL 2.0
16+
URL: http://pypi.python.org/pypi/%{{name}}
17+
Source0: http://pypi.python.org/lul/%{{name}}/%{{name}}-%{{version}}.tar.gz
18+
19+
BuildArch: noarch
20+
BuildRequires: python-setuptools
21+
BuildRequires: python2-devel
22+
23+
Requires: python-argparse
24+
Requires: python-iso8601
25+
Requires: python-prettytable
26+
27+
%description
28+
{name} is incredibly interesting and useful to all beings in universe.
29+
30+
It's pretty good stuff for a testing package that doesn't even exist.
31+
32+
%prep
33+
%setup -q
34+
35+
%build
36+
%{{__python}} setup.py build
37+
38+
%install
39+
%{{__python}} setup.py install -O1 --skip-build --root %{{buildroot}}
40+
41+
%files
42+
%doc README.rst
43+
%{{_bindir}}/{name}
44+
45+
%changelog
46+
* Mon Apr 23 2017 Jakub Ruzicka <jruzicka@redhat.com> {version}-{release}
47+
- Update to upstream {version}
48+
- Introduce new bugs (rhbz#123456)
49+
50+
* Tue Mar 23 2016 Jakub Ruzicka <jruzicka@redhat.com> 1.2.2-1
51+
- Update to upstream 1.2.2
52+
53+
* Tue Jun 23 2015 Jakub Ruzicka <jruzicka@redhat.com> 1.1.1-1
54+
- Update to upstream 1.1.1
55+
- Lorem Ipsum
56+
- Dolor sit Amet
57+
""" # noqa
58+
59+
60+
# silent run() by default
61+
def run(*args, **kwargs):
62+
kwargs['log_cmd'] = False
63+
return rdopkg.utils.cmd.run(*args, **kwargs)
64+
65+
66+
class SilentGit(rdopkg.utils.cmd.Git):
67+
def __call__(self, *args, **kwargs):
68+
if kwargs.get('log_cmd', None) is None:
69+
kwargs['log_cmd'] = False
70+
return super(SilentGit, self).__call__(*args, **kwargs)
71+
72+
73+
# silent git() by default
74+
git = SilentGit()
75+
76+
77+
def do_patch(fn, content, msg):
78+
f = open(fn, 'a')
79+
f.write(content)
80+
f.close()
81+
git('add', fn)
82+
git('commit', '-m', msg)
83+
84+
85+
def add_n_patches(n, patch_name='Test Patch %d',
86+
branch='master-patches'):
87+
if branch:
88+
old_branch = rdopkg.utils.cmd.git.current_branch()
89+
git('checkout', branch)
90+
for i in range(1, n + 1):
91+
pn = patch_name % i
92+
do_patch(pn, pn + '\n', pn)
93+
if branch:
94+
git('checkout', old_branch)
95+
96+
97+
def create_sample_distgit(name, version='1.2.3', release='1', path=None):
98+
if not path:
99+
path = name
100+
assert not os.path.exists(path)
101+
os.makedirs(path)
102+
with helpers.cdir(path):
103+
txt = SAMPLE_SPEC.format(name=name, version=version, release=release)
104+
spec = specfile.Spec(fn='%s.spec' % name, txt=txt)
105+
spec.set_tag('Name', name)
106+
spec.save()
107+
git('init',)
108+
git('add', '.')
109+
git('commit', '-m', 'Initial import', isolated=True)
110+
return os.path.abspath(path)
111+
112+
113+
def create_sample_patches_branch(n):
114+
version = specfile.Spec().get_tag('Version')
115+
branch = rdopkg.utils.cmd.git.current_branch()
116+
git('tag', version, fatal=False, log_fail=False)
117+
git('branch', '%s-patches' % branch)
118+
add_n_patches(n, patch_name="Original Patch %d")
119+
120+
121+
def create_sample_upstream_new_version(
122+
new_version, n_patches, n_from_patches_branch):
123+
branch = rdopkg.utils.cmd.git.current_branch()
124+
old_version = specfile.Spec().get_tag('Version')
125+
git('checkout', '-b', 'upstream', old_version)
126+
add_n_patches(n_patches,
127+
patch_name='Upstream Commit %d',
128+
branch=None)
129+
for i in range(n_from_patches_branch):
130+
# emulate upstream patches that were backported
131+
git('cherry-pick', 'master-patches' + i * '~')
132+
git('tag', new_version)
133+
git('checkout', branch)

run_tests.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ set -exuo pipefail
33

44
# avoid possible pytest errors due to precompiled files
55
export PYTHONDONTWRITEBYTECODE=1
6-
find . | grep -E "(__pycache__|\.pyc|\.pyo$)" | xargs rm -rf || true
6+
find . | grep -E "(__pycache__|\.pyc|\.pyo)$" | xargs rm -rf || true
77

88
PYTHONPATH=. py.test $@
9+
PYTHONPATH=. behave --format=progress
910
python -m pycodestyle
1011
./tests/test_findpkg_integration.sh

test-requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
pep8
2-
pytest
1+
behave
32
pycodestyle
3+
pytest

0 commit comments

Comments
 (0)