Skip to content

Commit

Permalink
Implement ls for test, testset and story commands
Browse files Browse the repository at this point in the history
  • Loading branch information
psss committed Oct 7, 2019
1 parent b26f1a4 commit 5e66169
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 21 deletions.
6 changes: 6 additions & 0 deletions stories/cli.fmf
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ story: As a user I want to have an intuitive command line interface
/ls:
story: 'List available tests'
examples: tmt test ls
implemented: /tmt/cli
tested: /tests/ls

/show:
story: 'Show test metadata'
Expand Down Expand Up @@ -192,6 +194,8 @@ story: As a user I want to have an intuitive command line interface
/ls:
story: 'List available testsets'
examples: tmt testset ls
implemented: /tmt/cli
tested: /tests/ls

/show:
story: 'Show testset configuration'
Expand All @@ -209,6 +213,8 @@ story: As a user I want to have an intuitive command line interface
/ls:
story: 'List available stories'
examples: tmt story ls
implemented: /tmt/cli
tested: /tests/ls

/show:
story: 'Show story details'
Expand Down
3 changes: 3 additions & 0 deletions tests/ls/example-story.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/stories/cli/story/ls:
story: 'List available stories'
examples: tmt story ls
7 changes: 7 additions & 0 deletions tests/ls/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ rlJournalStart
rlRun "TmpDir=\$(mktemp -d)" 0 "Creating tmp directory"
rlRun "cp example-test.txt $TmpDir/test.fmf"
rlRun "cp example-testset.txt $TmpDir/testset.fmf"
rlRun "cp example-story.txt $TmpDir/story.fmf"
rlRun "pushd $TmpDir"
rlRun "fmf init"
rlRun "set -o pipefail"
Expand All @@ -28,6 +29,12 @@ rlJournalStart
rlAssertNotGrep "/test/basic/smoke" "output"
rlPhaseEnd

rlPhaseStartTest "Test listing available stories"
rlRun "tmt story ls | tee output"
rlAssertGrep "/stories/cli/story/ls" "output"
rlAssertNotGrep "/test/basic/smoke" "output"
rlPhaseEnd

rlPhaseStartCleanup
rlRun "popd"
rlRun "rm -r $TmpDir" 0 "Removing tmp directory"
Expand Down
94 changes: 83 additions & 11 deletions tmt/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,82 @@
""" Base Metadata Classes """

from __future__ import unicode_literals, absolute_import
from click import echo, style

import fmf
import pprint

import tmt.steps


class Testset(object):
""" Group of tests sharing the same test execution metadata """
class Node(object):
"""
General node object
Corresponds to given fmf.Tree node.
Implements common Test, Testset and Story methods.
"""

def __init__(self, node):
""" Initialize testset steps """
""" Initialize the node """
self.node = node
self.name = node.name
self.summary = node.get('summary')

def __str__(self):
""" Node name """
return self.name

def name_and_summary(self):
""" Node name and optional summary """
if self.summary:
return '{0} ({1})'.format(self.name, self.summary)
else:
return self.name

def ls(self):
""" List node """
echo(style(self.name, fg='red'))

def show(self):
""" Show node details """
echo(style('{}: {}'.format(self.__class__.__name__, self), fg='green'))
if self.summary:
echo(style('Summary: {}'.format(self.summary), fg='green'))


class Test(Node):
""" Test object (L1 Metadata) """

def __init__(self, node):
""" Initialize test """
super(Test, self).__init__(node)


class Testset(Node):
""" Testset object (L2 Metadata) """

def __init__(self, node):
""" Initialize testset steps """
super(Testset, self).__init__(node)

# Initialize test steps
self.discover = tmt.steps.Discover(self.node.get('discover'))
self.provision = tmt.steps.Provision(self.node.get('provision'))
self.prepare = tmt.steps.Prepare(self.node.get('prepare'))
self.execute = tmt.steps.Execute(self.node.get('execute'))
self.report = tmt.steps.Report(self.node.get('report'))
self.finish = tmt.steps.Finish(self.node.get('finish'))

def __str__(self):
""" Testset name and summary """
if self.summary:
return '{0} ({1})'.format(self.name, self.summary)
else:
return self.name
# Relevant artifacts & gates (convert to list if needed)
self.artifacts = node.get('artifacts')
if self.artifacts:
if not isinstance(artifacts, list):
artifacts = [artifacts]
self.gates = node.get('gates')
if self.gates:
if not isinstance(gates, list):
gates = [gates]

def go(self):
""" Execute the testset """
Expand All @@ -42,11 +90,35 @@ def go(self):
self.finish.go()


class Story(Node):
""" User story object """

def __init__(self, node):
""" Initialize test """
super(Story, self).__init__(node)


class Tree(object):
""" Test Metadata Tree """

def __init__(self, path='.'):
""" Initialize testsets for given directory path """
self.tree = fmf.Tree(path)
self.testsets = [Testset(testset)
for testset in self.tree.prune(keys=['execute'])]

def tests(self, keys=[], names=[], filters=[], conditions=[]):
""" Search available tests """
keys.append('test')
return [Test(test) for test in self.tree.prune(
keys=keys, names=names, filters=filters, conditions=conditions)]

def testsets(self, keys=[], names=[], filters=[], conditions=[]):
""" Search available testsets """
keys.append('execute')
return [Testset(testset) for testset in self.tree.prune(
keys=keys, names=names, filters=filters, conditions=conditions)]

def stories(self, keys=[], names=[], filters=[], conditions=[]):
""" Search available stories """
keys.append('story')
return [Story(story) for story in self.tree.prune(
keys=keys, names=names, filters=filters, conditions=conditions)]
82 changes: 72 additions & 10 deletions tmt/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
""" Command line interface for the Test Metadata Tool """

from __future__ import unicode_literals, absolute_import, print_function
from click import echo, style

import fmf.utils
import click
Expand Down Expand Up @@ -47,7 +48,7 @@ def main(path):
@click.group(chain=True, invoke_without_command=True)
@click.pass_context
def run(context):
""" Run test steps (discover, prepare, execute...) """
""" Run test steps. """
# All test steps are enabled if no step selected
enabled = context.invoked_subcommand is None
tmt.steps.Discover.enabled = enabled
Expand Down Expand Up @@ -107,18 +108,26 @@ def finish():
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@click.group()
@click.pass_context
def test(context):
def test():
"""
Handle test metadata (investigate, filter, convert).
Manage tests (L1 metadata).
Check available tests, inspect their metadata, gather old metadata from
various sources and stored them in the new fmf format.
Check available tests, inspect their metadata.
Convert old metadata into the new fmf format.
"""

main.add_command(test)


@click.argument('names', nargs=-1, metavar='[REGEXP]...')
@test.command()
def ls(names):
""" List available tests. """
for test in tree.tests(names=names):
test.ls()
return 'test ls'


@click.option(
'--nitrate / --no-nitrate', default=True,
help='Import test metadata from Nitrate')
Expand Down Expand Up @@ -156,16 +165,69 @@ def convert(paths, makefile, nitrate, purpose):
tmt.convert.write(path, data)
return 'convert'

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Testset
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@click.group()
def testset():
"""
Manage testsets (L2 metadata).
\b
Search for available testsets.
Explore detailed test step configuration.
"""

main.add_command(testset)


@click.argument('names', nargs=-1, metavar='[REGEXP]...')
@testset.command()
def ls(names):
""" List available testsets. """
for testset in tree.testsets(names=names):
testset.ls()
return 'testset ls'


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Story
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

@click.group()
def story():
"""
Manage user stories.
\b
Check available user stories.
Explore coverage (test, implementation, documentation).
"""

main.add_command(story)


@click.argument('names', nargs=-1, metavar='[REGEXP]...')
@story.command()
def ls(names):
""" List available stories. """
for story in tree.stories(names=names):
story.ls()
return 'story ls'


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Go
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

def go():
""" Go and do test steps for selected testsets """
click.echo(click.style('Found {0}.'.format(
fmf.utils.listed(tree.testsets, 'testset')), fg='magenta'))
for testset in tree.testsets:
click.echo(click.style('\nTestset: {0}'.format(testset), fg='green'))
echo(style('Found {0}.'.format(
fmf.utils.listed(tree.testsets(), 'testset')), fg='magenta'))
for testset in tree.testsets():
echo()
testset.show()
testset.go()

# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down

0 comments on commit 5e66169

Please sign in to comment.