Skip to content
This repository has been archived by the owner on Nov 21, 2019. It is now read-only.

Implement empty response #1

Merged
merged 21 commits into from
Feb 4, 2019
Merged

Implement empty response #1

merged 21 commits into from
Feb 4, 2019

Conversation

giorgiosironi
Copy link
Member

Forked master into a branch, create a new master with just README.md and merged it into this branch to make sure they have a common ancestor.

@giorgiosironi giorgiosironi requested a review from a team as a code owner January 30, 2019 16:49
.travis.yml Outdated Show resolved Hide resolved
.travis.yml Show resolved Hide resolved
CODE_OF_CONDUCT.md Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
README.md Outdated Show resolved Hide resolved
web:
build:
context: ..
dockerfile: docker/Dockerfile.dev
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this correctly, all of these images will be created when referencing this file. Is that correct? I don't see the advantage of having everything in one file. Could you explain please?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could leave the test and prod image for later when we setup a pipeline

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. Was just bit concerned that this looked like it would be a dev-only container.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is at the moment (doesn't have the code), but it should be transformed into a prod container derivative as soon as the prod container image is there

response = client.get('/search')
assert response.status == '200 OK'
assert response.data == (b'<?xml version="1.0" encoding="UTF-8"?>'
b'<item-list xmlns="http://libero.pub"/>')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would prefer testing the structure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you provide an example please?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some equivalent of https://phpunit.readthedocs.io/en/7.4/assertions.html#assertxmlstringequalsxmlstring, so makes sure that two XML documents are the equal rather than two strings being the same.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the example you have linked to is actually testing against two strings and the function is entitled assertxmlstringequalsxmlstring which suggests the same.

In the test, response.data is the actual data. What it's being checked against looks like a string but is a string representation of the byte data, hence the little b at the beginning. I'm not aware of a better way to represent this in python but I'm open to suggestions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

>>> from lxml import etree
>>> etree.fromstring(b'<?xml version="1.0" encoding="UTF-8"?><item-list xmlns="http://libero.pub"></item-list>').getchildren() == []
True

but the syntax may vary depending on the XML library being used.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@giorgiosironi I see. So what is missing from the test is checking that item-list doesn't have child elements?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the example you have linked to is actually testing against two strings and the function is entitled assertxmlstringequalsxmlstring which suggests the same.

Strings of XML, so it recognises <item-list xmlns="http://libero.pub"></item-list> and <item-list xmlns="http://libero.pub"/> as equal.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewilkybarkid oh I see. I totally missed that. I'll see what I can do.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have reimplemented the xml generation and parsing using the lxml library.

docker/Dockerfile.dev Outdated Show resolved Hide resolved
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PATH "/root/.poetry/bin:$PATH"
RUN curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a (versioned) container that can be used?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is inferred in the pyproject.toml file.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm referring to Poetry itself, like https://hub.docker.com/_/composer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. There are some floating around on Docker Hub but not an official image.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From what we have seen yesterday, no luck: have to install Poetry on top of a python official image

@@ -0,0 +1,19 @@
[flake8]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It'd be good to have a configured coding-standard checker as a dependency, this was started in https://github.com/elifesciences/proofreader-python.

We have https://github.com/libero/php-coding-standard which is applied across all the PHP repos and saves having to try and replicate the same configuration everywhere. It does only do the one tool though, but is the one that needs the fine-grained control.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. I would like to see how this project evolves and, once well established, move the coding standard checks to its own repo. A separate issue should be created for this though and prioritised accordingly.

@thewilkybarkid
Copy link
Contributor

Two other things we need to do:

  • Error format
  • /ping route

(See also https://github.com/libero/api-problem-bundle and https://github.com/libero/ping-controller.)

.travis.yml Outdated Show resolved Hide resolved
@GiancarloFusiello
Copy link
Contributor

@thewilkybarkid implementing /ping is not in the requirements for this issue. Can we create a separate issue for this please?

docker/Dockerfile.dev Outdated Show resolved Hide resolved
assert response.content_type == 'application/xml; charset=utf-8'
assert xml.docinfo.encoding == 'UTF-8'
assert xml.docinfo.xml_version == '1.0'
assert xml.docinfo.root_name == 'item-list'
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably don't need this as it's checked in the next line, but doesn't matter much


from lxml import etree

LIBERO_NAMESPACE = 'http://libero.pub'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this use http or https? spec says http but thought I would double check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are not URLs that will actually be loaded, they only serve the purpose to avoid clashes between different organizations that could choose the same namespace:
https://en.wikipedia.org/wiki/XML_namespace#Namespace_names

apk del .build-dependencies

COPY ./pyproject.toml ./
COPY ./poetry.lock ./
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple files can be done in one COPY.

gcc \
musl-dev \
&& \
poetry config settings.virtualenvs.create false && \
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can probably push poetry config up too when it is installed? Very minor

curl -sSL https://raw.githubusercontent.com/sdispater/poetry/master/get-poetry.py | python && \
apk del .build-dependencies

COPY ./pyproject.toml ./
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can probably merge these two COPY into one (it's like cp)

Copy link
Member Author

@giorgiosironi giorgiosironi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't formally approve on Github because I opened this PR, but 👍 from me as my comments have been addressed. Left a few more on minor things

assert xml.docinfo.encoding == 'UTF-8'
assert xml.docinfo.xml_version == '1.0'
assert xml.docinfo.root_name == 'item-list'
assert root.tag == '{http://libero.pub}item-list' # check namespace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all looks rather unsustainable: not that many lines for an empty list, but as soon as there's one with content...

In fact, doesn't actually check that the list in empty?

Still think an equivalent of assertXmlStringEqualsXmlString is a better approach.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In fact, doesn't actually check that the list in empty?

I suggested a separate test for that case, since this one is oriented to "schema" checks more than content. I do think checking actual listings will be different and this is a test not to be replicated: in the case of a listing we would extract the list of elements with Xpath and check the presence of what we have added but you don't want to write

assert response == \
           '<item-list xmlns="http://libero.pub">' \
           '<item-ref id="42">' \
           '</item-list>'

when you can write:

    self.assertFoundItems([42])

or even

    self.assertFoundItems([42])
    self.assertNotFoundItems([43])

for negative cases and similar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Full expected responses have their place to demonstrate a sample of what it should look like, but this is a service which returns a flat list so there's not much explanatory power in replicating the full document for all cases.

Even with JSON you would never write:

    assertJsonEquals(items, '[{"key":"value", ...}]')

but the expected value would still be a data structure in the source code, as a string is prone to syntax errors.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewilkybarkid @giorgiosironi I can't find anything like the php assertion method in python. Also, it seems it's not trivial to compare python xml tree objects. lxml has the ability to check a document against a schema. Would this be a better way to test xml?

Copy link
Contributor

@thewilkybarkid thewilkybarkid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still a few things to tidy up, but can be resolved by the time we deploy though.

@giorgiosironi
Copy link
Member Author

Good for me 👍

@GiancarloFusiello
Copy link
Contributor

Ok. I'll merge for now and happy to revisit individual aspects.

@GiancarloFusiello GiancarloFusiello merged commit 0eae6bd into master Feb 4, 2019
@GiancarloFusiello GiancarloFusiello deleted the empty_response branch February 4, 2019 12:00
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants