mirror of
https://github.com/haidaraM/ansible-playbook-grapher
synced 2024-11-10 14:14:19 +00:00
Tests and Travis Integration (#9)
* Test for grapher and post_processor (To complete) * Udpate readme * Add requirements.txt and update setup.py * Add .travis.yml
This commit is contained in:
parent
af9a03c99e
commit
a363eae94b
16 changed files with 379 additions and 21 deletions
20
.travis.yml
Normal file
20
.travis.yml
Normal file
|
@ -0,0 +1,20 @@
|
|||
language: python
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.5"
|
||||
|
||||
env:
|
||||
- ANSIBLE_VERSION=2.4.0
|
||||
- ANSIBLE_VERSION=2.4.1
|
||||
|
||||
before_install:
|
||||
- sudo apt-get -qq update
|
||||
- sudo apt-get install -y graphviz
|
||||
|
||||
install:
|
||||
- pip install -q ansible==$ANSIBLE_VERSION
|
||||
- pip install -q -r requirements.txt
|
||||
- pip install .
|
||||
|
||||
script:
|
||||
- make test
|
3
Makefile
3
Makefile
|
@ -17,6 +17,9 @@ setup_virtualenv:
|
|||
|
||||
test_install: build setup_virtualenv
|
||||
|
||||
test:
|
||||
pytest
|
||||
|
||||
clean:
|
||||
@echo "Cleaning..."
|
||||
@rm -rf ansible_playbook_grapher.egg-info build dist $(VIRTUALENV_DIR) example.svg
|
||||
|
|
11
Readme.md
11
Readme.md
|
@ -1,5 +1,6 @@
|
|||
# Ansible Playbook Grapher
|
||||
|
||||
[![Build Status](https://travis-ci.org/haidaraM/ansible-playbook-grapher.svg?branch=master)](https://travis-ci.org/haidaraM/ansible-playbook-grapher)
|
||||
[![PyPI version](https://badge.fury.io/py/ansible-playbook-grapher.svg)](https://badge.fury.io/py/ansible-playbook-grapher)
|
||||
|
||||
[ansible-playbook-grapher](https://github.com/haidaraM/ansible-playbook-grapher) is a command line tool to create a graph representing your Ansible playbook tasks and roles. The aim of
|
||||
|
@ -7,11 +8,9 @@ this project is to quickly have an overview of your playbook.
|
|||
|
||||
Inspired by [Ansible Inventory Grapher](https://github.com/willthames/ansible-inventory-grapher).
|
||||
|
||||
## Pérequis
|
||||
* **Ansible** >= 2.4: The script has not been tested yet with an earlier version of Ansible.
|
||||
```
|
||||
$ sudo pip3 install 'ansible>=2.4'
|
||||
```
|
||||
## Prerequisites
|
||||
* **Ansible** >= 2.4: The script has not been tested with an earlier version of Ansible. If you still use an older version of Ansible, create an virtual environment and install ansible-playbook-grapher. **The installation process will install a version of Ansible >= 2.4**
|
||||
|
||||
* **graphviz**: The tool used to generate the graph in SVG.
|
||||
```
|
||||
$ sudo apt-get install graphviz
|
||||
|
@ -19,7 +18,7 @@ Inspired by [Ansible Inventory Grapher](https://github.com/willthames/ansible-in
|
|||
|
||||
## Installation
|
||||
```
|
||||
$ sudo pip3 install ansible-playbook-grapher
|
||||
$ pip install ansible-playbook-grapher
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
|
|
@ -128,7 +128,7 @@ class Grapher(object):
|
|||
|
||||
color, play_font_color = self._colors_for_play(play)
|
||||
|
||||
play_name = "hosts: {} ({})".format(clean_name(str(play)), nb_hosts)
|
||||
play_name = "{} ({})".format(clean_name(str(play)), nb_hosts)
|
||||
|
||||
play_name = self.template(play_name, play_vars)
|
||||
|
||||
|
@ -227,9 +227,9 @@ class Grapher(object):
|
|||
if output_filename is None:
|
||||
output_filename = self.output_filename + ".svg"
|
||||
|
||||
post_processor = PostProcessor(svg_path=output_filename, graph_representation=self.graph_representation)
|
||||
post_processor = PostProcessor(svg_path=output_filename)
|
||||
|
||||
post_processor.post_process()
|
||||
post_processor.post_process(graph_representation=self.graph_representation)
|
||||
|
||||
post_processor.write()
|
||||
|
||||
|
|
|
@ -77,14 +77,11 @@ class PostProcessor(object):
|
|||
Post process the svg by adding some javascript and css
|
||||
"""
|
||||
|
||||
def __init__(self, svg_path, graph_representation):
|
||||
def __init__(self, svg_path):
|
||||
self.svg_path = svg_path
|
||||
self.graph_representation = graph_representation
|
||||
self.tree = etree.parse(svg_path)
|
||||
self.root = self.tree.getroot()
|
||||
|
||||
self.root.set('id', 'svg')
|
||||
|
||||
def insert_script_tag(self, index, attrib):
|
||||
element_script_tag = etree.Element('script', attrib=attrib)
|
||||
|
||||
|
@ -107,7 +104,9 @@ class PostProcessor(object):
|
|||
|
||||
graph_group_element.remove(title_element)
|
||||
|
||||
def post_process(self, *args, **kwargs):
|
||||
def post_process(self, graph_representation=None, *args, **kwargs):
|
||||
|
||||
self.root.set('id', 'svg')
|
||||
|
||||
jquery_tag_index = 0
|
||||
javascript_tag_index = 1
|
||||
|
@ -118,19 +117,19 @@ class PostProcessor(object):
|
|||
|
||||
# insert my javascript
|
||||
highlight_script = _read_data("highlight-hover.js")
|
||||
self.insert_cdata(javascript_tag_index, 'script', attrib={'type': 'text/javascript'},
|
||||
self.insert_cdata(javascript_tag_index, 'script', attrib={'type': 'text/javascript', 'id': 'my_javascript'},
|
||||
cdata_text=highlight_script)
|
||||
|
||||
css = _read_data("graph.css")
|
||||
|
||||
# insert my css
|
||||
self.insert_cdata(css_tag_index, 'style', attrib={'type': 'text/css'}, cdata_text=css)
|
||||
self.insert_cdata(css_tag_index, 'style', attrib={'type': 'text/css', 'id': 'my_css'}, cdata_text=css)
|
||||
|
||||
self._remove_title()
|
||||
|
||||
if self.graph_representation:
|
||||
if graph_representation:
|
||||
# insert the graph representation for the links between the nodes
|
||||
self._insert_graph_representation()
|
||||
self._insert_graph_representation(graph_representation)
|
||||
|
||||
def write(self, output_filename=None):
|
||||
if output_filename is None:
|
||||
|
@ -138,8 +137,8 @@ class PostProcessor(object):
|
|||
|
||||
self.tree.write(output_filename, xml_declaration=True, encoding="UTF-8")
|
||||
|
||||
def _insert_graph_representation(self):
|
||||
for node, node_links in self.graph_representation.graph_dict.items():
|
||||
def _insert_graph_representation(self, graph_representation):
|
||||
for node, node_links in graph_representation.graph_dict.items():
|
||||
# Find the group g with the specified id
|
||||
element = self.root.xpath("ns:g/*[@id='%s']" % node, namespaces={'ns': SVG_NAMESPACE})[0]
|
||||
|
||||
|
|
3
pytest.ini
Normal file
3
pytest.ini
Normal file
|
@ -0,0 +1,3 @@
|
|||
[pytest]
|
||||
rootdir = tests
|
||||
addopts = -v
|
4
requirements.txt
Normal file
4
requirements.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
ansible>=2.4.0
|
||||
graphviz==0.8.1
|
||||
colour==0.1.5
|
||||
lxml==4.1.1
|
3
setup.py
3
setup.py
|
@ -14,7 +14,8 @@ setup(name=__prog__,
|
|||
author="HAIDARA Mohamed El Mouctar",
|
||||
author_email="elmhaidara@gmail.com",
|
||||
license="MIT",
|
||||
install_requires=['graphviz', 'colour', 'lxml'],
|
||||
install_requires=['graphviz==0.8.1', 'colour==0.1.5', 'lxml==4.1.1', 'ansible>=2.4'],
|
||||
tests_requires=['pytest'],
|
||||
packages=find_packages(exclude=['tests']),
|
||||
package_data={"ansible-playbook-grapher": ['data/*']},
|
||||
include_package_data=True,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
FIXTURES_DIR = 'tests/fixtures/'
|
||||
INVENTORY_FILE = FIXTURES_DIR + "inventory"
|
||||
|
||||
SIMPLE_PLAYBOOK_YML = FIXTURES_DIR + "simple_playbook.yml"
|
||||
SIMPLE_PLAYBOOK_SVG = FIXTURES_DIR + "simple_playbook_no_postproccess.svg"
|
40
tests/conftest.py
Normal file
40
tests/conftest.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import pytest
|
||||
|
||||
from ansibleplaybookgrapher.grapher import Grapher
|
||||
from tests import INVENTORY_FILE
|
||||
|
||||
|
||||
@pytest.fixture(name='data_loader')
|
||||
def fixture_data_loader():
|
||||
"""
|
||||
Return an Ansible DataLoader
|
||||
:return:
|
||||
"""
|
||||
from ansible.parsing.dataloader import DataLoader
|
||||
return DataLoader()
|
||||
|
||||
|
||||
@pytest.fixture(name='inventory_manager')
|
||||
def fixture_inventory_manager(data_loader):
|
||||
"""
|
||||
Return an Ansible InventoryManager
|
||||
:return:
|
||||
"""
|
||||
from ansible.inventory.manager import InventoryManager
|
||||
return InventoryManager(loader=data_loader, sources=INVENTORY_FILE)
|
||||
|
||||
|
||||
@pytest.fixture(name='variable_manager')
|
||||
def fixture_variable_manager(data_loader, inventory_manager):
|
||||
"""
|
||||
Return an Ansible VariableManager
|
||||
:return:
|
||||
"""
|
||||
from ansible.vars.manager import VariableManager
|
||||
return VariableManager(loader=data_loader, inventory=inventory_manager)
|
||||
|
||||
|
||||
@pytest.fixture(name='grapher')
|
||||
def fixture_simple_grapher(data_loader, inventory_manager, variable_manager, request):
|
||||
return Grapher(data_loader=data_loader, inventory_manager=inventory_manager, variable_manager=variable_manager,
|
||||
playbook_filename=request.param)
|
40
tests/fixtures/example.yml
vendored
Normal file
40
tests/fixtures/example.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
- hosts: all
|
||||
vars:
|
||||
backport: "stretch-backports"
|
||||
packages:
|
||||
- git
|
||||
- tree
|
||||
- curl
|
||||
pre_tasks:
|
||||
- name: Pre task 1
|
||||
debug: msg="Pretask"
|
||||
- name: Pre task 2
|
||||
debug: msg="Pretask"
|
||||
|
||||
tasks:
|
||||
- name: Add the backbport
|
||||
become: yes
|
||||
apt_repository:
|
||||
repo: deb http://ftp.debian.org/debian {{backport}} main
|
||||
filename: "{{backport}}"
|
||||
state: present
|
||||
|
||||
- name: Install packages
|
||||
become: yes
|
||||
apt:
|
||||
name: "{{item}}"
|
||||
state: present
|
||||
default_release: "{{backport}}"
|
||||
with_items: "{{packages}}"
|
||||
|
||||
- name: Command that should fails
|
||||
command: /bin/false
|
||||
ignore_errors: true
|
||||
|
||||
post_tasks:
|
||||
- name: Post task 1
|
||||
debug: msg="Postask"
|
||||
|
||||
- name: Posttask 2
|
||||
debug: msg="Postask"
|
6
tests/fixtures/inventory
vendored
Normal file
6
tests/fixtures/inventory
vendored
Normal file
|
@ -0,0 +1,6 @@
|
|||
host1
|
||||
host2
|
||||
host3
|
||||
host4
|
||||
host5
|
||||
host6
|
8
tests/fixtures/simple_playbook.yml
vendored
Normal file
8
tests/fixtures/simple_playbook.yml
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
- hosts: all
|
||||
post_tasks:
|
||||
- name: Post task 1
|
||||
debug: msg="Postask"
|
||||
|
||||
- name: Posttask 2
|
||||
debug: msg="Postask"
|
80
tests/fixtures/simple_playbook_no_postproccess.svg
vendored
Normal file
80
tests/fixtures/simple_playbook_no_postproccess.svg
vendored
Normal file
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 2.38.0 (20140413.2041)
|
||||
-->
|
||||
<!-- Title: %3 Pages: 1 -->
|
||||
<svg width="628pt" height="98pt"
|
||||
viewBox="0.00 0.00 627.65 98.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 94)">
|
||||
<title>%3</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-94 623.654,-94 623.654,4 -4,4"/>
|
||||
<!-- tests/fixtures/simple_playbook.yml -->
|
||||
<g id="node1" class="node">
|
||||
<title>tests/fixtures/simple_playbook.yml</title>
|
||||
<ellipse fill="none" stroke="black" stroke-dasharray="1,5" cx="135.838" cy="-45" rx="135.676" ry="18"/>
|
||||
<text text-anchor="middle" x="135.838" y="-41.3" font-family="Times,serif" font-size="14.00">
|
||||
tests/fixtures/simple_playbook.yml
|
||||
</text>
|
||||
</g>
|
||||
<!-- hosts: all -->
|
||||
<g id="play_hostsall" class="node">
|
||||
<title>hosts: all</title>
|
||||
<polygon fill="#483337" stroke="#483337"
|
||||
points="379.676,-63 314.676,-63 314.676,-27 379.676,-27 379.676,-63"/>
|
||||
<text text-anchor="middle" x="347.176" y="-41.3" font-family="Times,serif" font-size="14.00" fill="#ffffff">
|
||||
hosts: all
|
||||
</text>
|
||||
</g>
|
||||
<!-- tests/fixtures/simple_playbook.yml->hosts: all -->
|
||||
<g id="testsfixturessimple_playbookymlhostsall" class="edge">
|
||||
<title>tests/fixtures/simple_playbook.yml->hosts: all</title>
|
||||
<path fill="none" stroke="#483337" stroke-width="2" d="M271.782,-45C283.402,-45 294.477,-45 304.364,-45"/>
|
||||
<polygon fill="#483337" stroke="#483337" stroke-width="2"
|
||||
points="304.595,-48.5001 314.595,-45 304.595,-41.5001 304.595,-48.5001"/>
|
||||
<text text-anchor="middle" x="293.176" y="-48.8" font-family="Times,serif" font-size="14.00" fill="#483337">
|
||||
1
|
||||
</text>
|
||||
</g>
|
||||
<!-- [post_task] Post task 1 -->
|
||||
<g id="post_taskPosttask1" class="node">
|
||||
<title>[post_task] Post task 1</title>
|
||||
<polygon fill="none" stroke="black"
|
||||
points="619.643,-64.5442 619.643,-79.4558 561.956,-90 480.374,-90 422.687,-79.4558 422.687,-64.5442 480.374,-54 561.956,-54 619.643,-64.5442"/>
|
||||
<text text-anchor="middle" x="521.165" y="-68.3" font-family="Times,serif" font-size="14.00">[post_task]
|
||||
Post task 1
|
||||
</text>
|
||||
</g>
|
||||
<!-- hosts: all->[post_task] Post task 1 -->
|
||||
<g id="play_hostsallpost_taskPosttask1" class="edge">
|
||||
<title>hosts: all->[post_task] Post task 1</title>
|
||||
<path fill="none" stroke="#483337" stroke-width="2"
|
||||
d="M379.721,-49.9522C395.567,-52.4397 415.602,-55.585 435.539,-58.7149"/>
|
||||
<polygon fill="#483337" stroke="#483337" stroke-width="2"
|
||||
points="435.193,-62.2034 445.615,-60.2967 436.279,-55.2881 435.193,-62.2034"/>
|
||||
<text text-anchor="middle" x="401.176" y="-56.8" font-family="Times,serif" font-size="14.00" fill="#483337">
|
||||
1
|
||||
</text>
|
||||
</g>
|
||||
<!-- [post_task] Posttask 2 -->
|
||||
<g id="post_taskPosttask2" class="node">
|
||||
<title>[post_task] Posttask 2</title>
|
||||
<polygon fill="none" stroke="black"
|
||||
points="617.015,-10.5442 617.015,-25.4558 560.867,-36 481.462,-36 425.315,-25.4558 425.315,-10.5442 481.462,-3.55271e-15 560.867,-0 617.015,-10.5442"/>
|
||||
<text text-anchor="middle" x="521.165" y="-14.3" font-family="Times,serif" font-size="14.00">[post_task]
|
||||
Posttask 2
|
||||
</text>
|
||||
</g>
|
||||
<!-- hosts: all->[post_task] Posttask 2 -->
|
||||
<g id="play_hostsallpost_taskPosttask2" class="edge">
|
||||
<title>hosts: all->[post_task] Posttask 2</title>
|
||||
<path fill="none" stroke="#483337" stroke-width="2"
|
||||
d="M379.747,-36.7686C385.678,-35.3868 391.847,-34.0598 397.676,-33 406.252,-31.4407 415.197,-29.9982 424.175,-28.6747"/>
|
||||
<polygon fill="#483337" stroke="#483337" stroke-width="2"
|
||||
points="424.903,-32.1065 434.309,-27.2311 423.916,-25.1764 424.903,-32.1065"/>
|
||||
<text text-anchor="middle" x="401.176" y="-36.8" font-family="Times,serif" font-size="14.00" fill="#483337">
|
||||
2
|
||||
</text>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 4.6 KiB |
25
tests/test_grapher.py
Normal file
25
tests/test_grapher.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
import os
|
||||
from lxml import etree
|
||||
|
||||
from ansibleplaybookgrapher.grapher import Grapher
|
||||
from tests import FIXTURES_DIR
|
||||
|
||||
|
||||
def test_grapher_simple_playbook(data_loader, inventory_manager, variable_manager, tmpdir):
|
||||
playbook = FIXTURES_DIR + "simple_playbook.yml"
|
||||
output_filepath = tmpdir.join('output')
|
||||
grapher = Grapher(data_loader=data_loader, inventory_manager=inventory_manager, variable_manager=variable_manager,
|
||||
playbook_filename=playbook, output_filename=output_filepath.strpath)
|
||||
|
||||
grapher.make_graph()
|
||||
|
||||
grapher.render_graph()
|
||||
|
||||
grapher.post_process_svg()
|
||||
|
||||
svg_filepath = output_filepath.strpath + ".svg"
|
||||
|
||||
# test if the file exist. It will exist only if we write in it
|
||||
assert os.path.isfile(svg_filepath)
|
||||
|
||||
tree = etree.parse(svg_filepath)
|
125
tests/test_postprocessor.py
Normal file
125
tests/test_postprocessor.py
Normal file
|
@ -0,0 +1,125 @@
|
|||
import pytest
|
||||
from lxml import etree
|
||||
|
||||
from ansibleplaybookgrapher.utils import PostProcessor, SVG_NAMESPACE, GraphRepresentation
|
||||
from tests import SIMPLE_PLAYBOOK_SVG
|
||||
|
||||
|
||||
@pytest.fixture(name='post_processor')
|
||||
def fixture_simple_postprocessor(request):
|
||||
"""
|
||||
Return a post processor without a graph representation and with the simple_playbook_no_postproccess
|
||||
:return:
|
||||
"""
|
||||
try:
|
||||
svg_path = request.param
|
||||
except AttributeError:
|
||||
# if the svg is not provided, we use the simple one
|
||||
svg_path = SIMPLE_PLAYBOOK_SVG
|
||||
|
||||
post_processor = PostProcessor(svg_path=svg_path)
|
||||
return post_processor
|
||||
|
||||
|
||||
def _assert_common_svg(svg_root):
|
||||
"""
|
||||
Assert some common structures of the generated svg
|
||||
:param svg_root:
|
||||
:return:
|
||||
"""
|
||||
|
||||
assert svg_root.get('id') == 'svg'
|
||||
|
||||
# jquery must be the first element because the next script need jquery
|
||||
assert svg_root[0].get('id') == 'jquery'
|
||||
assert svg_root[1].get('id') == 'my_javascript'
|
||||
assert svg_root[2].get('id') == 'my_css'
|
||||
|
||||
|
||||
def test_post_processor_insert_tag(post_processor):
|
||||
"""
|
||||
Test method insert_tag of the PostProcessor
|
||||
:param post_processor:
|
||||
:return:
|
||||
"""
|
||||
post_processor.insert_script_tag(0, attrib={'id': 'toto'})
|
||||
|
||||
assert post_processor.root[0].tag == 'script'
|
||||
assert post_processor.root[0].get('id') == 'toto'
|
||||
|
||||
|
||||
def test_post_processor_remove_title(post_processor):
|
||||
"""
|
||||
Test method _remove_title of the PostProcessor
|
||||
:param post_processor:
|
||||
:return:
|
||||
"""
|
||||
post_processor._remove_title()
|
||||
root = post_processor.root
|
||||
resultats = root.xpath("ns:g[@id='graph0']/ns:title", namespaces={'ns': SVG_NAMESPACE})
|
||||
|
||||
assert len(resultats) == 0
|
||||
|
||||
|
||||
def test_post_processor_write(post_processor, tmpdir):
|
||||
"""
|
||||
Test method write of the PostProcessor
|
||||
:param post_processor:
|
||||
:return:
|
||||
"""
|
||||
svg_post_proccessed_path = tmpdir.join("test_post_processor_write.svg")
|
||||
post_processor.write(output_filename=svg_post_proccessed_path.strpath)
|
||||
|
||||
assert svg_post_proccessed_path.check(file=1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("post_processor", [SIMPLE_PLAYBOOK_SVG], indirect=True)
|
||||
def test_post_processor_without_graph_representation(post_processor, tmpdir):
|
||||
"""
|
||||
Test the post processor without a graph representation
|
||||
:param post_processor:
|
||||
:param tmpdir:
|
||||
:return:
|
||||
"""
|
||||
svg_post_proccessed_path = tmpdir.join("simple_playbook_postproccess_no_graph.svg")
|
||||
|
||||
post_processor.post_process()
|
||||
|
||||
post_processor.write(output_filename=svg_post_proccessed_path.strpath)
|
||||
|
||||
assert svg_post_proccessed_path.check(file=1)
|
||||
|
||||
root = etree.parse(svg_post_proccessed_path.strpath).getroot()
|
||||
_assert_common_svg(root)
|
||||
|
||||
# no links should be in the svg when there is no graph_representation
|
||||
assert len(root.xpath("//ns:links", namespaces={'ns': SVG_NAMESPACE})) == 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize("post_processor", [SIMPLE_PLAYBOOK_SVG], indirect=True)
|
||||
def test_post_processor_with_graph_representation(post_processor, tmpdir):
|
||||
"""
|
||||
Test the post processor a graph representation
|
||||
:param post_processor:
|
||||
:param tmpdir:
|
||||
:return:
|
||||
"""
|
||||
graph_represention = GraphRepresentation()
|
||||
svg_post_proccessed_path = tmpdir.join("simple_playbook_postproccess_graph.svg")
|
||||
|
||||
play_id = "play_hostsall"
|
||||
# link from play to task edges
|
||||
graph_represention.add_link(play_id, "play_hostsallpost_taskPosttask1")
|
||||
graph_represention.add_link(play_id, "play_hostsallpost_taskPosttask2")
|
||||
|
||||
post_processor.post_process(graph_represention)
|
||||
|
||||
post_processor.write(output_filename=svg_post_proccessed_path.strpath)
|
||||
|
||||
assert svg_post_proccessed_path.check(file=1)
|
||||
|
||||
root = etree.parse(svg_post_proccessed_path.strpath).getroot()
|
||||
|
||||
_assert_common_svg(root)
|
||||
|
||||
assert len(root.xpath("ns:g/*[@id='%s']//ns:link" % play_id, namespaces={'ns': SVG_NAMESPACE})) == 2
|
Loading…
Reference in a new issue