Repository: pydicom/pydicom

Issue:
Unexpected EOF warning when reading dataset saved to DicomBytesIO
```python
from python import read_file
from python.filebase import DicomBytesIO
ds = read_file('ct_small.dcm')
fp = DicomBytesIO()
ds.save_as(fp)
fp.seek(0)
read_file(fp)
```
Dataset gets read correctly but logs message:

> Unexpected end of file. Read 0 bytes of 8 expected starting at position 0x98d2 in file <no filename>

Caused by `EOFError` exception in `filereader.data_element_generator` [from this line](https://github.com/darcymason/pydicom/blob/master/pydicom/filereader.py#L188) being [caught](https://github.com/darcymason/pydicom/blob/master/pydicom/filereader.py#L357) in `read_dataset`.

I'm not really sure what the best way to deal with it is. I don't want to add the overhead of checking how much is left in the stream. Is there a reason for logging the error instead of just passing?

Discussion:
pep8speaks: Hello @mrbean-bremen! Thanks for submitting the PR.



 - In the file [`pydicom/tests/test_filewriter.py`](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py), following are the PEP8 issues :

> [Line 21:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L21): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 30:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L30): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 31:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L31): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 32:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L32): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 33:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L33): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 34:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L34): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 35:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L35): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 37:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L37): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 38:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L38): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 39:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L39): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 40:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L40): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 41:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L41): [E402](https://duckduckgo.com/?q=pep8%20E402) module level import not at top of file
> [Line 68:1](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L68): [E302](https://duckduckgo.com/?q=pep8%20E302) expected 2 blank lines, found 1
> [Line 86:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L86): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (83 > 79 characters)
> [Line 105:47](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L105): [E225](https://duckduckgo.com/?q=pep8%20E225) missing whitespace around operator
> [Line 180:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L180): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 211:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L211): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (119 > 79 characters)
> [Line 212:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L212): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (101 > 79 characters)
> [Line 213:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L213): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (126 > 79 characters)
> [Line 214:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L214): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (119 > 79 characters)
> [Line 215:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L215): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (101 > 79 characters)
> [Line 300:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L300): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (82 > 79 characters)
> [Line 301:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L301): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (84 > 79 characters)
> [Line 344:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L344): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (82 > 79 characters)
> [Line 345:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L345): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (84 > 79 characters)
> [Line 506:53](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L506): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 513:53](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L513): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 520:53](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L520): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 531:59](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L531): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 556:39](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L556): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 557:58](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L557): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 560:59](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L560): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 586:39](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L586): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 606:42](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L606): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 607:58](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L607): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 610:59](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L610): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 624:42](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L624): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 635:59](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L635): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 636:37](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L636): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 637:58](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L637): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 644:59](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L644): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 646:58](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L646): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 692:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L692): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (84 > 79 characters)
> [Line 697:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L697): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (89 > 79 characters)
> [Line 698:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L698): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (81 > 79 characters)
> [Line 724:53](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L724): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 742:53](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L742): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 797:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L797): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (90 > 79 characters)
> [Line 803:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L803): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (82 > 79 characters)
> [Line 829:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L829): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (80 > 79 characters)
> [Line 851:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L851): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 853:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L853): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 877:37](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L877): [E701](https://duckduckgo.com/?q=pep8%20E701) multiple statements on one line (colon)
> [Line 878:37](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L878): [E701](https://duckduckgo.com/?q=pep8%20E701) multiple statements on one line (colon)
> [Line 891:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L891): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (80 > 79 characters)
> [Line 905:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L905): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 913:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L913): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (94 > 79 characters)
> [Line 916:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L916): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 919:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L919): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 921:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L921): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 932:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L932): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 939:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L939): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (85 > 79 characters)
> [Line 949:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L949): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1003:50](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1003): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1073:47](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1073): [E225](https://duckduckgo.com/?q=pep8%20E225) missing whitespace around operator
> [Line 1090:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1090): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (80 > 79 characters)
> [Line 1110:37](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1110): [E701](https://duckduckgo.com/?q=pep8%20E701) multiple statements on one line (colon)
> [Line 1111:37](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1111): [E701](https://duckduckgo.com/?q=pep8%20E701) multiple statements on one line (colon)
> [Line 1133:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1133): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1149:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1149): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1167:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1167): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1182:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1182): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1210:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1210): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (95 > 79 characters)
> [Line 1212:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1212): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1232:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1232): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (95 > 79 characters)
> [Line 1234:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1234): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1253:9](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1253): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 1253:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1253): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (96 > 79 characters)
> [Line 1255:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1255): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1279:9](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1279): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 1279:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1279): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (96 > 79 characters)
> [Line 1281:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1281): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1304:9](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1304): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 1304:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1304): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (96 > 79 characters)
> [Line 1306:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1306): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1330:9](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1330): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 1330:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1330): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (96 > 79 characters)
> [Line 1332:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1332): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1353:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1353): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (95 > 79 characters)
> [Line 1355:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1355): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1375:9](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1375): [E265](https://duckduckgo.com/?q=pep8%20E265) block comment should start with '# '
> [Line 1375:80](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1375): [E501](https://duckduckgo.com/?q=pep8%20E501) line too long (96 > 79 characters)
> [Line 1377:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1377): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1387:25](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1387): [E127](https://duckduckgo.com/?q=pep8%20E127) continuation line over-indented for visual indent
> [Line 1410:41](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1410): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment
> [Line 1507:49](https://github.com/pydicom/pydicom/blob/915a8b45091df535a91309e9045305877329c1e2/pydicom/tests/test_filewriter.py#L1507): [E261](https://duckduckgo.com/?q=pep8%20E261) at least two spaces before inline comment


mrbean-bremen: Waiting until #443 is merged, where the PEP-8 issues are solved.
mrbean-bremen: That's why I'm separating the pep8 changes into a separate commit, as I did in #443, so you can review both commits separately. Also, here I did only a very small change in the affected file, so this will be no problem. 
scaramallion: You haven't changed `read_leUS`, `read_beUS`, `read_leUL` and `read_beUL`?
scaramallion: Actually, can you add a failing unit test that reproduces #358?

Patch:
diff --git a/pydicom/data/__init__.py b/pydicom/data/__init__.py
new file mode 100644
index 000000000..c1c542e0b
--- /dev/null
+++ b/pydicom/data/__init__.py
@@ -0,0 +1,12 @@
+"""pydicom data manager"""
+#
+# Copyright (c) 2008-2012 Darcy Mason
+# Copyright (c) 2017 pydicom AUTHORS
+# This file is part of pydicom, released under a modified MIT license.
+#    See the file LICENSE included with this distribution, also
+#    available at https://github.com/pydicom/pydicom
+#
+
+from .base import (get_charset_files,
+                   get_testdata_files,
+                   DATA_ROOT)
diff --git a/pydicom/data/base.py b/pydicom/data/base.py
new file mode 100644
index 000000000..5fc7b3cdf
--- /dev/null
+++ b/pydicom/data/base.py
@@ -0,0 +1,50 @@
+"""pydicom data manager"""
+#
+# Copyright (c) 2008-2012 Darcy Mason
+# Copyright (c) 2017 pydicom AUTHORS
+# This file is part of pydicom, released under a modified MIT license.
+#    See the file LICENSE included with this distribution, also
+#    available at https://github.com/pydicom/pydicom
+#
+
+from os.path import abspath, dirname, join
+from .utils import get_files
+
+
+DATA_ROOT = abspath(dirname(__file__))
+
+
+def get_testdata_files(pattern="*"):
+    """Return test data files from pydicom data root
+
+    Parameters
+    ----------
+    pattern : string
+            A string pattern to filter the files
+
+    Returns
+    ----------
+    files : list of test data files
+
+    """
+
+    data_path = join(DATA_ROOT, 'test_files')
+    return get_files(bases=data_path, pattern=pattern)
+
+
+def get_charset_files(pattern="*"):
+    """Return charset files from pydicom data root
+
+    Parameters
+    ----------
+    pattern : string
+            A string pattern to filter the files
+
+    Returns
+    ----------
+    files : list of charset data files
+
+    """
+
+    data_path = join(DATA_ROOT, 'charset_files')
+    return get_files(bases=data_path, pattern=pattern)
diff --git a/pydicom/tests/charset_files/FileInfo.txt b/pydicom/data/charset_files/FileInfo.txt
similarity index 100%
rename from pydicom/tests/charset_files/FileInfo.txt
rename to pydicom/data/charset_files/FileInfo.txt
diff --git a/pydicom/data/charset_files/__init__.py b/pydicom/data/charset_files/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/charset_files/charlist.py b/pydicom/data/charset_files/charlist.py
similarity index 100%
rename from pydicom/tests/charset_files/charlist.py
rename to pydicom/data/charset_files/charlist.py
diff --git a/pydicom/tests/charset_files/chrArab.dcm b/pydicom/data/charset_files/chrArab.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrArab.dcm
rename to pydicom/data/charset_files/chrArab.dcm
diff --git a/pydicom/tests/charset_files/chrFren.dcm b/pydicom/data/charset_files/chrFren.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrFren.dcm
rename to pydicom/data/charset_files/chrFren.dcm
diff --git a/pydicom/tests/charset_files/chrFrenMulti.dcm b/pydicom/data/charset_files/chrFrenMulti.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrFrenMulti.dcm
rename to pydicom/data/charset_files/chrFrenMulti.dcm
diff --git a/pydicom/tests/charset_files/chrGerm.dcm b/pydicom/data/charset_files/chrGerm.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrGerm.dcm
rename to pydicom/data/charset_files/chrGerm.dcm
diff --git a/pydicom/tests/charset_files/chrGreek.dcm b/pydicom/data/charset_files/chrGreek.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrGreek.dcm
rename to pydicom/data/charset_files/chrGreek.dcm
diff --git a/pydicom/tests/charset_files/chrH31.dcm b/pydicom/data/charset_files/chrH31.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrH31.dcm
rename to pydicom/data/charset_files/chrH31.dcm
diff --git a/pydicom/tests/charset_files/chrH32.dcm b/pydicom/data/charset_files/chrH32.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrH32.dcm
rename to pydicom/data/charset_files/chrH32.dcm
diff --git a/pydicom/tests/charset_files/chrHbrw.dcm b/pydicom/data/charset_files/chrHbrw.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrHbrw.dcm
rename to pydicom/data/charset_files/chrHbrw.dcm
diff --git a/pydicom/tests/charset_files/chrI2.dcm b/pydicom/data/charset_files/chrI2.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrI2.dcm
rename to pydicom/data/charset_files/chrI2.dcm
diff --git a/pydicom/tests/charset_files/chrJapMulti.dcm b/pydicom/data/charset_files/chrJapMulti.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrJapMulti.dcm
rename to pydicom/data/charset_files/chrJapMulti.dcm
diff --git a/pydicom/tests/charset_files/chrJapMultiExplicitIR6.dcm b/pydicom/data/charset_files/chrJapMultiExplicitIR6.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrJapMultiExplicitIR6.dcm
rename to pydicom/data/charset_files/chrJapMultiExplicitIR6.dcm
diff --git a/pydicom/tests/charset_files/chrKoreanMulti.dcm b/pydicom/data/charset_files/chrKoreanMulti.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrKoreanMulti.dcm
rename to pydicom/data/charset_files/chrKoreanMulti.dcm
diff --git a/pydicom/tests/charset_files/chrRuss.dcm b/pydicom/data/charset_files/chrRuss.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrRuss.dcm
rename to pydicom/data/charset_files/chrRuss.dcm
diff --git a/pydicom/tests/charset_files/chrSQEncoding.dcm b/pydicom/data/charset_files/chrSQEncoding.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrSQEncoding.dcm
rename to pydicom/data/charset_files/chrSQEncoding.dcm
diff --git a/pydicom/tests/charset_files/chrX1.dcm b/pydicom/data/charset_files/chrX1.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrX1.dcm
rename to pydicom/data/charset_files/chrX1.dcm
diff --git a/pydicom/tests/charset_files/chrX2.dcm b/pydicom/data/charset_files/chrX2.dcm
similarity index 100%
rename from pydicom/tests/charset_files/chrX2.dcm
rename to pydicom/data/charset_files/chrX2.dcm
diff --git a/pydicom/tests/test_files/CT_small.dcm b/pydicom/data/test_files/CT_small.dcm
similarity index 100%
rename from pydicom/tests/test_files/CT_small.dcm
rename to pydicom/data/test_files/CT_small.dcm
diff --git a/pydicom/tests/test_files/ExplVR_BigEnd.dcm b/pydicom/data/test_files/ExplVR_BigEnd.dcm
similarity index 100%
rename from pydicom/tests/test_files/ExplVR_BigEnd.dcm
rename to pydicom/data/test_files/ExplVR_BigEnd.dcm
diff --git a/pydicom/tests/test_files/ExplVR_BigEndNoMeta.dcm b/pydicom/data/test_files/ExplVR_BigEndNoMeta.dcm
similarity index 100%
rename from pydicom/tests/test_files/ExplVR_BigEndNoMeta.dcm
rename to pydicom/data/test_files/ExplVR_BigEndNoMeta.dcm
diff --git a/pydicom/tests/test_files/ExplVR_LitEndNoMeta.dcm b/pydicom/data/test_files/ExplVR_LitEndNoMeta.dcm
similarity index 100%
rename from pydicom/tests/test_files/ExplVR_LitEndNoMeta.dcm
rename to pydicom/data/test_files/ExplVR_LitEndNoMeta.dcm
diff --git a/pydicom/tests/test_files/JPEG-LL.dcm b/pydicom/data/test_files/JPEG-LL.dcm
similarity index 100%
rename from pydicom/tests/test_files/JPEG-LL.dcm
rename to pydicom/data/test_files/JPEG-LL.dcm
diff --git a/pydicom/tests/test_files/JPEG-lossy.dcm b/pydicom/data/test_files/JPEG-lossy.dcm
similarity index 100%
rename from pydicom/tests/test_files/JPEG-lossy.dcm
rename to pydicom/data/test_files/JPEG-lossy.dcm
diff --git a/pydicom/tests/test_files/JPEG2000.dcm b/pydicom/data/test_files/JPEG2000.dcm
similarity index 100%
rename from pydicom/tests/test_files/JPEG2000.dcm
rename to pydicom/data/test_files/JPEG2000.dcm
diff --git a/pydicom/tests/test_files/MR_small.dcm b/pydicom/data/test_files/MR_small.dcm
similarity index 100%
rename from pydicom/tests/test_files/MR_small.dcm
rename to pydicom/data/test_files/MR_small.dcm
diff --git a/pydicom/tests/test_files/MR_small_RLE.dcm b/pydicom/data/test_files/MR_small_RLE.dcm
similarity index 100%
rename from pydicom/tests/test_files/MR_small_RLE.dcm
rename to pydicom/data/test_files/MR_small_RLE.dcm
diff --git a/pydicom/tests/test_files/MR_small_jp2klossless.dcm b/pydicom/data/test_files/MR_small_jp2klossless.dcm
similarity index 100%
rename from pydicom/tests/test_files/MR_small_jp2klossless.dcm
rename to pydicom/data/test_files/MR_small_jp2klossless.dcm
diff --git a/pydicom/tests/test_files/MR_small_jpeg_ls_lossless.dcm b/pydicom/data/test_files/MR_small_jpeg_ls_lossless.dcm
similarity index 100%
rename from pydicom/tests/test_files/MR_small_jpeg_ls_lossless.dcm
rename to pydicom/data/test_files/MR_small_jpeg_ls_lossless.dcm
diff --git a/pydicom/tests/test_files/MR_truncated.dcm b/pydicom/data/test_files/MR_truncated.dcm
similarity index 100%
rename from pydicom/tests/test_files/MR_truncated.dcm
rename to pydicom/data/test_files/MR_truncated.dcm
diff --git a/pydicom/tests/test_files/OBXXXX1A.dcm b/pydicom/data/test_files/OBXXXX1A.dcm
similarity index 100%
rename from pydicom/tests/test_files/OBXXXX1A.dcm
rename to pydicom/data/test_files/OBXXXX1A.dcm
diff --git a/pydicom/tests/test_files/OT-PAL-8-face.dcm b/pydicom/data/test_files/OT-PAL-8-face.dcm
similarity index 100%
rename from pydicom/tests/test_files/OT-PAL-8-face.dcm
rename to pydicom/data/test_files/OT-PAL-8-face.dcm
diff --git a/pydicom/tests/test_files/README.txt b/pydicom/data/test_files/README.txt
similarity index 100%
rename from pydicom/tests/test_files/README.txt
rename to pydicom/data/test_files/README.txt
diff --git a/pydicom/data/test_files/__init__.py b/pydicom/data/test_files/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/test_files/badVR.dcm b/pydicom/data/test_files/badVR.dcm
similarity index 100%
rename from pydicom/tests/test_files/badVR.dcm
rename to pydicom/data/test_files/badVR.dcm
diff --git a/pydicom/tests/test_files/color-pl.dcm b/pydicom/data/test_files/color-pl.dcm
similarity index 100%
rename from pydicom/tests/test_files/color-pl.dcm
rename to pydicom/data/test_files/color-pl.dcm
diff --git a/pydicom/tests/test_files/color-px.dcm b/pydicom/data/test_files/color-px.dcm
similarity index 100%
rename from pydicom/tests/test_files/color-px.dcm
rename to pydicom/data/test_files/color-px.dcm
diff --git a/pydicom/tests/test_files/color3d_jpeg_baseline.dcm b/pydicom/data/test_files/color3d_jpeg_baseline.dcm
similarity index 100%
rename from pydicom/tests/test_files/color3d_jpeg_baseline.dcm
rename to pydicom/data/test_files/color3d_jpeg_baseline.dcm
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CR1/6154 b/pydicom/data/test_files/dicomdirtests/77654033/CR1/6154
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CR1/6154
rename to pydicom/data/test_files/dicomdirtests/77654033/CR1/6154
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CR2/6247 b/pydicom/data/test_files/dicomdirtests/77654033/CR2/6247
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CR2/6247
rename to pydicom/data/test_files/dicomdirtests/77654033/CR2/6247
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CR3/6278 b/pydicom/data/test_files/dicomdirtests/77654033/CR3/6278
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CR3/6278
rename to pydicom/data/test_files/dicomdirtests/77654033/CR3/6278
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CT2/17106 b/pydicom/data/test_files/dicomdirtests/77654033/CT2/17106
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CT2/17106
rename to pydicom/data/test_files/dicomdirtests/77654033/CT2/17106
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CT2/17136 b/pydicom/data/test_files/dicomdirtests/77654033/CT2/17136
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CT2/17136
rename to pydicom/data/test_files/dicomdirtests/77654033/CT2/17136
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CT2/17166 b/pydicom/data/test_files/dicomdirtests/77654033/CT2/17166
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CT2/17166
rename to pydicom/data/test_files/dicomdirtests/77654033/CT2/17166
diff --git a/pydicom/tests/test_files/dicomdirtests/77654033/CT2/17196 b/pydicom/data/test_files/dicomdirtests/77654033/CT2/17196
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/77654033/CT2/17196
rename to pydicom/data/test_files/dicomdirtests/77654033/CT2/17196
diff --git a/pydicom/data/test_files/dicomdirtests/77654033/__init__.py b/pydicom/data/test_files/dicomdirtests/77654033/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT2N/6293 b/pydicom/data/test_files/dicomdirtests/98892001/CT2N/6293
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT2N/6293
rename to pydicom/data/test_files/dicomdirtests/98892001/CT2N/6293
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT2N/6924 b/pydicom/data/test_files/dicomdirtests/98892001/CT2N/6924
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT2N/6924
rename to pydicom/data/test_files/dicomdirtests/98892001/CT2N/6924
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2062 b/pydicom/data/test_files/dicomdirtests/98892001/CT5N/2062
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2062
rename to pydicom/data/test_files/dicomdirtests/98892001/CT5N/2062
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2392 b/pydicom/data/test_files/dicomdirtests/98892001/CT5N/2392
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2392
rename to pydicom/data/test_files/dicomdirtests/98892001/CT5N/2392
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2693 b/pydicom/data/test_files/dicomdirtests/98892001/CT5N/2693
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT5N/2693
rename to pydicom/data/test_files/dicomdirtests/98892001/CT5N/2693
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT5N/3023 b/pydicom/data/test_files/dicomdirtests/98892001/CT5N/3023
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT5N/3023
rename to pydicom/data/test_files/dicomdirtests/98892001/CT5N/3023
diff --git a/pydicom/tests/test_files/dicomdirtests/98892001/CT5N/3353 b/pydicom/data/test_files/dicomdirtests/98892001/CT5N/3353
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892001/CT5N/3353
rename to pydicom/data/test_files/dicomdirtests/98892001/CT5N/3353
diff --git a/pydicom/data/test_files/dicomdirtests/98892001/__init__.py b/pydicom/data/test_files/dicomdirtests/98892001/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR1/15820 b/pydicom/data/test_files/dicomdirtests/98892003/MR1/15820
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR1/15820
rename to pydicom/data/test_files/dicomdirtests/98892003/MR1/15820
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR1/4919 b/pydicom/data/test_files/dicomdirtests/98892003/MR1/4919
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR1/4919
rename to pydicom/data/test_files/dicomdirtests/98892003/MR1/4919
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR1/5641 b/pydicom/data/test_files/dicomdirtests/98892003/MR1/5641
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR1/5641
rename to pydicom/data/test_files/dicomdirtests/98892003/MR1/5641
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/15970 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/15970
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/15970
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/15970
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/4950 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/4950
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/4950
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/4950
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/4981 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/4981
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/4981
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/4981
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/5011 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/5011
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/5011
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/5011
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/6273 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/6273
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/6273
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/6273
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/6605 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/6605
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/6605
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/6605
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR2/6935 b/pydicom/data/test_files/dicomdirtests/98892003/MR2/6935
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR2/6935
rename to pydicom/data/test_files/dicomdirtests/98892003/MR2/6935
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4467 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4467
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4467
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4467
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4528 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4528
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4528
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4528
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4558 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4558
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4558
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4558
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4588 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4588
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4588
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4588
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4618 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4618
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4618
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4618
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4648 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4648
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4648
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4648
diff --git a/pydicom/tests/test_files/dicomdirtests/98892003/MR700/4678 b/pydicom/data/test_files/dicomdirtests/98892003/MR700/4678
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/98892003/MR700/4678
rename to pydicom/data/test_files/dicomdirtests/98892003/MR700/4678
diff --git a/pydicom/data/test_files/dicomdirtests/98892003/__init__.py b/pydicom/data/test_files/dicomdirtests/98892003/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/test_files/dicomdirtests/DICOMDIR b/pydicom/data/test_files/dicomdirtests/DICOMDIR
similarity index 100%
rename from pydicom/tests/test_files/dicomdirtests/DICOMDIR
rename to pydicom/data/test_files/dicomdirtests/DICOMDIR
diff --git a/pydicom/data/test_files/dicomdirtests/__init__.py b/pydicom/data/test_files/dicomdirtests/__init__.py
new file mode 100644
index 000000000..e69de29bb
diff --git a/pydicom/tests/test_files/emri_small.dcm b/pydicom/data/test_files/emri_small.dcm
similarity index 100%
rename from pydicom/tests/test_files/emri_small.dcm
rename to pydicom/data/test_files/emri_small.dcm
diff --git a/pydicom/tests/test_files/emri_small_RLE.dcm b/pydicom/data/test_files/emri_small_RLE.dcm
similarity index 100%
rename from pydicom/tests/test_files/emri_small_RLE.dcm
rename to pydicom/data/test_files/emri_small_RLE.dcm
diff --git a/pydicom/tests/test_files/emri_small_big_endian.dcm b/pydicom/data/test_files/emri_small_big_endian.dcm
similarity index 100%
rename from pydicom/tests/test_files/emri_small_big_endian.dcm
rename to pydicom/data/test_files/emri_small_big_endian.dcm
diff --git a/pydicom/tests/test_files/emri_small_jpeg_2k_lossless.dcm b/pydicom/data/test_files/emri_small_jpeg_2k_lossless.dcm
similarity index 100%
rename from pydicom/tests/test_files/emri_small_jpeg_2k_lossless.dcm
rename to pydicom/data/test_files/emri_small_jpeg_2k_lossless.dcm
diff --git a/pydicom/tests/test_files/emri_small_jpeg_ls_lossless.dcm b/pydicom/data/test_files/emri_small_jpeg_ls_lossless.dcm
similarity index 100%
rename from pydicom/tests/test_files/emri_small_jpeg_ls_lossless.dcm
rename to pydicom/data/test_files/emri_small_jpeg_ls_lossless.dcm
diff --git a/pydicom/tests/test_files/image_dfl.dcm b/pydicom/data/test_files/image_dfl.dcm
similarity index 100%
rename from pydicom/tests/test_files/image_dfl.dcm
rename to pydicom/data/test_files/image_dfl.dcm
diff --git a/pydicom/tests/test_files/meta_missing_tsyntax.dcm b/pydicom/data/test_files/meta_missing_tsyntax.dcm
similarity index 100%
rename from pydicom/tests/test_files/meta_missing_tsyntax.dcm
rename to pydicom/data/test_files/meta_missing_tsyntax.dcm
diff --git a/pydicom/tests/test_files/nested_priv_SQ.dcm b/pydicom/data/test_files/nested_priv_SQ.dcm
similarity index 100%
rename from pydicom/tests/test_files/nested_priv_SQ.dcm
rename to pydicom/data/test_files/nested_priv_SQ.dcm
diff --git a/pydicom/tests/test_files/no_meta_group_length.dcm b/pydicom/data/test_files/no_meta_group_length.dcm
similarity index 100%
rename from pydicom/tests/test_files/no_meta_group_length.dcm
rename to pydicom/data/test_files/no_meta_group_length.dcm
diff --git a/pydicom/tests/test_files/priv_SQ.dcm b/pydicom/data/test_files/priv_SQ.dcm
similarity index 100%
rename from pydicom/tests/test_files/priv_SQ.dcm
rename to pydicom/data/test_files/priv_SQ.dcm
diff --git a/pydicom/tests/test_files/reportsi.dcm b/pydicom/data/test_files/reportsi.dcm
similarity index 100%
rename from pydicom/tests/test_files/reportsi.dcm
rename to pydicom/data/test_files/reportsi.dcm
diff --git a/pydicom/tests/test_files/reportsi_with_empty_number_tags.dcm b/pydicom/data/test_files/reportsi_with_empty_number_tags.dcm
similarity index 100%
rename from pydicom/tests/test_files/reportsi_with_empty_number_tags.dcm
rename to pydicom/data/test_files/reportsi_with_empty_number_tags.dcm
diff --git a/pydicom/tests/test_files/rtdose.dcm b/pydicom/data/test_files/rtdose.dcm
similarity index 100%
rename from pydicom/tests/test_files/rtdose.dcm
rename to pydicom/data/test_files/rtdose.dcm
diff --git a/pydicom/tests/test_files/rtplan.dcm b/pydicom/data/test_files/rtplan.dcm
similarity index 100%
rename from pydicom/tests/test_files/rtplan.dcm
rename to pydicom/data/test_files/rtplan.dcm
diff --git a/pydicom/tests/test_files/rtplan.dump b/pydicom/data/test_files/rtplan.dump
similarity index 100%
rename from pydicom/tests/test_files/rtplan.dump
rename to pydicom/data/test_files/rtplan.dump
diff --git a/pydicom/tests/test_files/rtplan_truncated.dcm b/pydicom/data/test_files/rtplan_truncated.dcm
similarity index 100%
rename from pydicom/tests/test_files/rtplan_truncated.dcm
rename to pydicom/data/test_files/rtplan_truncated.dcm
diff --git a/pydicom/tests/test_files/rtstruct.dcm b/pydicom/data/test_files/rtstruct.dcm
similarity index 100%
rename from pydicom/tests/test_files/rtstruct.dcm
rename to pydicom/data/test_files/rtstruct.dcm
diff --git a/pydicom/tests/test_files/rtstruct.dump b/pydicom/data/test_files/rtstruct.dump
similarity index 100%
rename from pydicom/tests/test_files/rtstruct.dump
rename to pydicom/data/test_files/rtstruct.dump
diff --git a/pydicom/tests/test_files/test-SR.dcm b/pydicom/data/test_files/test-SR.dcm
similarity index 100%
rename from pydicom/tests/test_files/test-SR.dcm
rename to pydicom/data/test_files/test-SR.dcm
diff --git a/pydicom/tests/test_files/test.py b/pydicom/data/test_files/test.py
similarity index 100%
rename from pydicom/tests/test_files/test.py
rename to pydicom/data/test_files/test.py
diff --git a/pydicom/tests/test_files/zipMR.gz b/pydicom/data/test_files/zipMR.gz
similarity index 100%
rename from pydicom/tests/test_files/zipMR.gz
rename to pydicom/data/test_files/zipMR.gz
diff --git a/pydicom/data/utils.py b/pydicom/data/utils.py
new file mode 100644
index 000000000..7ae8f09cd
--- /dev/null
+++ b/pydicom/data/utils.py
@@ -0,0 +1,48 @@
+"""pydicom data manager utils"""
+#
+# Copyright (c) 2008-2012 Darcy Mason
+# Copyright (c) 2017 pydicom AUTHORS
+# This file is part of pydicom, released under a modified MIT license.
+#    See the file LICENSE included with this distribution, also
+#    available at https://github.com/pydicom/pydicom
+#
+
+import os
+import fnmatch
+
+
+def get_files(bases, pattern=None):
+    """Return all files from a set of sources.
+
+    Parameters
+    ----------
+    bases : list or file-like
+            This can be a list of files and/or folders conforming
+            to some standard pattern.
+    pattern : string for fnmatch
+            A string pattern to filter the files
+
+    Returns
+    ----------
+    files : list of files recursively found
+            from the bases
+    """
+
+    if pattern is None:
+        pattern = "*"
+
+    if not isinstance(bases, (list, tuple)):
+        bases = [bases]
+
+    files = []
+    for contender in bases:
+        if os.path.isdir(contender):
+
+            for root, dirnames, filenames in os.walk(contender):
+                for filename in fnmatch.filter(filenames, pattern):
+                    files.append(os.path.join(root, filename))
+
+        else:
+            files.append(contender)
+
+    return files
diff --git a/pydicom/dataelem.py b/pydicom/dataelem.py
index 36315e0ba..ea60bc4d0 100644
--- a/pydicom/dataelem.py
+++ b/pydicom/dataelem.py
@@ -14,6 +14,8 @@ A DataElement has a tag,
 from __future__ import absolute_import
 from collections import namedtuple
 
+from pydicom.multival import MultiValue
+
 from pydicom.charset import default_encoding
 
 from pydicom import config  # don't import datetime_conversion directly
@@ -230,10 +232,7 @@ class DataElement(object):
         except AttributeError:  # not a list
             return self._convert(val)
         else:
-            returnvalue = []
-            for subval in val:
-                returnvalue.append(self._convert(subval))
-            return returnvalue
+            return MultiValue(lambda x: self._convert(x), val)
 
     def _convert(self, val):
         """Convert `val` to an appropriate type for the element's VR."""
diff --git a/pydicom/dataset.py b/pydicom/dataset.py
index 4d3774bad..69b68f7ef 100644
--- a/pydicom/dataset.py
+++ b/pydicom/dataset.py
@@ -147,6 +147,7 @@ class Dataset(dict):
 
     def __exit__(self, exc_type, exc_val, exc_tb):
         """Method invoked on exit from a with statement."""
+        # Returning False will re-raise any exceptions that occur
         return False
 
     def add(self, data_element):
@@ -624,7 +625,7 @@ class Dataset(dict):
             yield self[tag]
 
     def _is_uncompressed_transfer_syntax(self):
-        """Return True if the TransferSyntaxUID is a compressed syntax."""
+        """Return True if the TransferSyntaxUID is not a compressed syntax."""
         # FIXME uses file_meta here, should really only be thus for FileDataset
         return self.file_meta.TransferSyntaxUID in (
             UncompressedPixelTransferSyntaxes)
@@ -680,6 +681,7 @@ class Dataset(dict):
             already_have = False
         elif self._pixel_id != id(self.PixelData):
             already_have = False
+
         if not already_have:
             last_exception = None
             successfully_read_pixel_data = False
diff --git a/pydicom/filebase.py b/pydicom/filebase.py
index 449dd4c02..11327635e 100644
--- a/pydicom/filebase.py
+++ b/pydicom/filebase.py
@@ -30,19 +30,13 @@ class DicomIO(object):
     def read_le_tag(self):
         """Read and return two unsigned shorts (little endian)
            from the file."""
-        bytes_read = self.read(4)
-        if len(bytes_read) < 4:
-            # needed for reading "next" tag when at end of file
-            raise EOFError
+        bytes_read = self.read(4, need_exact_length=True)
         return unpack(b"<HH", bytes_read)
 
     def read_be_tag(self):
-        """Read and return two unsigned shorts (little endian)
+        """Read and return two unsigned shorts (big endian)
            from the file."""
-        bytes_read = self.read(4)
-        if len(bytes_read) < 4:
-            # needed for reading "next" tag when at end of file
-            raise EOFError
+        bytes_read = self.read(4, need_exact_length=True)
         return unpack(b">HH", bytes_read)
 
     def write_tag(self, tag):
@@ -67,7 +61,7 @@ class DicomIO(object):
            little endian byte order"""
         return unpack(b"<L", self.read(4))[0]
 
-    def read(self, length=None, need_exact_length=True):
+    def read(self, length=None, need_exact_length=False):
         """Reads the required length, returns
         EOFError if gets less
 
diff --git a/pydicom/filewriter.py b/pydicom/filewriter.py
index a10c77884..17286a413 100644
--- a/pydicom/filewriter.py
+++ b/pydicom/filewriter.py
@@ -1,24 +1,22 @@
-# filewriter.py
-"""Write a dicom media file."""
+# Copyright 2008-2017 pydicom authors. See LICENSE file for details.
+"""Functions related to writing DICOM data."""
 from __future__ import absolute_import
-# Copyright (c) 2008-2012 Darcy Mason
-# This file is part of pydicom, released under a modified MIT license.
-#    See the file license.txt included with this distribution, also
-#    available at https://github.com/darcymason/pydicom
 
 from struct import pack
 
-from pydicom import compat
+from pydicom import compat, __version__
 from pydicom.compat import in_py2
 from pydicom.charset import default_encoding, text_VRs, convert_encodings
-from pydicom.uid import ImplicitVRLittleEndian, ExplicitVRBigEndian
-from pydicom.filebase import DicomFile, DicomFileLike
 from pydicom.datadict import keyword_for_tag
 from pydicom.dataset import Dataset
+from pydicom.filebase import DicomFile, DicomFileLike
+from pydicom.multival import MultiValue
 from pydicom.tag import Tag, ItemTag, ItemDelimiterTag, SequenceDelimiterTag
+from pydicom.tagtools import tag_in_exception
+from pydicom.uid import (PYDICOM_IMPLEMENTATION_UID, ImplicitVRLittleEndian,
+                         ExplicitVRBigEndian)
 from pydicom.valuerep import extra_length_VRs
 from pydicom.values import convert_numbers
-from pydicom.tagtools import tag_in_exception
 
 
 def correct_ambiguous_vr_element(elem, ds, is_little_endian):
@@ -203,9 +201,14 @@ def write_UI(fp, data_element):
     write_string(fp, data_element, '\0')  # pad with 0-byte to even length
 
 
+def _is_multi_value(val):
+    """Return True if `val` is a multi-value container."""
+    return isinstance(val, (MultiValue, list, tuple))
+
+
 def multi_string(val):
     """Put a string together with delimiter if has more than one value"""
-    if isinstance(val, (list, tuple)):
+    if _is_multi_value(val):
         # \ is escape chr, so "\\" gives single backslash
         return "\\".join(val)
     else:
@@ -251,7 +254,7 @@ def write_number_string(fp, data_element, padding=' '):
     # file
     val = data_element.value
 
-    if isinstance(val, (list, tuple)):
+    if _is_multi_value(val):
         val = "\\".join((x.original_string
                          if hasattr(x, 'original_string') else str(x)
                          for x in val))
@@ -284,7 +287,7 @@ def write_DA(fp, data_element, padding=' '):
     if isinstance(val, (str, compat.string_types)):
         write_string(fp, data_element, padding)
     else:
-        if isinstance(val, (list, tuple)):
+        if _is_multi_value(val):
             val = "\\".join((x if isinstance(x, (str, compat.string_types))
                              else _format_DA(x) for x in val))
         else:
@@ -312,7 +315,7 @@ def write_DT(fp, data_element, padding=' '):
     if isinstance(val, (str, compat.string_types)):
         write_string(fp, data_element, padding)
     else:
-        if isinstance(val, (list, tuple)):
+        if _is_multi_value(val):
             val = "\\".join((x if isinstance(x, (str, compat.string_types))
                              else _format_DT(x) for x in val))
         else:
@@ -342,7 +345,7 @@ def write_TM(fp, data_element, padding=' '):
     if isinstance(val, (str, compat.string_types)):
         write_string(fp, data_element, padding)
     else:
-        if isinstance(val, (list, tuple)):
+        if _is_multi_value(val):
             val = "\\".join((x if isinstance(x, (str, compat.string_types))
                              else _format_TM(x) for x in val))
         else:
@@ -523,10 +526,10 @@ def write_file_meta_info(fp, file_meta, enforce_standard=True):
         * (0002,0012) ImplementationClassUID, UI, N
 
     If `enforce_standard` is True then (0002,0000) will be added/updated,
-    (0002,0001) will be added if not already present and the other required
-    elements will checked to see if they exist. If `enforce_standard` is
-    False then `file_meta` will be written as is after minimal validation
-    checking.
+    (0002,0001) and (0002,0012) will be added if not already present and the
+    other required elements will be checked to see if they exist. If
+    `enforce_standard` is False then `file_meta` will be written as is after
+    minimal validation checking.
 
     The following Type 3/1C Elements may also be present:
         * (0002,0013) ImplementationVersionName, SH, N
@@ -536,6 +539,8 @@ def write_file_meta_info(fp, file_meta, enforce_standard=True):
         * (0002,0100) PrivateInformationCreatorUID, UI, N
         * (0002,0102) PrivateInformation, OB, N
 
+    If `enforce_standard` is True then (0002,0013) will be added/updated.
+
     Encoding
     ~~~~~~~~
     The encoding of the File Meta Information shall be Explicit VR Little
@@ -557,7 +562,7 @@ def write_file_meta_info(fp, file_meta, enforce_standard=True):
     ValueError
         If `enforce_standard` is True and any of the required File Meta
         Information elements are missing from `file_meta`, with the
-        exception of (0002,0000) and (0002,0001).
+        exception of (0002,0000), (0002,0001) and (0002,0012).
     ValueError
         If any non-Group 2 Elements are present in `file_meta`.
     """
@@ -578,9 +583,12 @@ def write_file_meta_info(fp, file_meta, enforce_standard=True):
         if 'FileMetaInformationVersion' not in file_meta:
             file_meta.FileMetaInformationVersion = b'\x00\x01'
 
+        file_meta.ImplementationClassUID = PYDICOM_IMPLEMENTATION_UID
+        file_meta.ImplementationVersionName = 'PYDICOM ' + __version__
+
         # Check that required File Meta Elements are present
         missing = []
-        for element in [0x0002, 0x0003, 0x0010, 0x0012]:
+        for element in [0x0002, 0x0003, 0x0010]:
             if Tag(0x0002, element) not in file_meta:
                 missing.append(Tag(0x0002, element))
         if missing:
@@ -753,7 +761,8 @@ def write_file(filename, dataset, write_like_original=True):
     #   `write_like_original` is True we treat it as optional
     file_meta = getattr(dataset, 'file_meta', None)
     if not file_meta and not write_like_original:
-        file_meta = Dataset()
+        dataset.file_meta = Dataset()
+        file_meta = dataset.file_meta
 
     # If enforcing the standard, correct the TransferSyntaxUID where possible,
     #   noting that the transfer syntax for is_implicit_VR = False and
@@ -768,6 +777,11 @@ def write_file(filename, dataset, write_like_original=True):
             raise NotImplementedError("Implicit VR Big Endian is not a"
                                       "supported Transfer Syntax.")
 
+        if 'SOPClassUID' in dataset:
+            file_meta.MediaStorageSOPClassUID = dataset.SOPClassUID
+        if 'SOPInstanceUID' in dataset:
+            file_meta.MediaStorageSOPInstanceUID = dataset.SOPInstanceUID
+
     caller_owns_file = True
     # Open file if not already a file object
     if isinstance(filename, compat.string_types):
diff --git a/pydicom/multival.py b/pydicom/multival.py
index 0829ac76a..5bc72b0d4 100644
--- a/pydicom/multival.py
+++ b/pydicom/multival.py
@@ -8,9 +8,10 @@ or any list of items that must all be the same type.
 #    See the file LICENSE included with this distribution, also
 #    available at https://github.com/pydicom/pydicom
 #
+from collections import MutableSequence
 
 
-class MultiValue(list):
+class MultiValue(MutableSequence):
     """Class to hold any multi-valued DICOM value,
     or any list of items that are all of the same type.
 
@@ -38,39 +39,44 @@ class MultiValue(list):
         """
         from pydicom.valuerep import DSfloat, DSdecimal, IS
 
-        self.type_constructor = type_constructor
-
-        if isinstance(type_constructor, (DSfloat, IS, DSdecimal)):
-            converted_list = [
-                type_constructor(x) if x != '' else x for x in iterable
-            ]
-        else:
-            converted_list = [type_constructor(x) for x in iterable]
-        super(MultiValue, self).__init__(converted_list)
+        def number_string_type_constructor(x):
+            return self.type_constructor(x) if x != '' else x
 
-    def append(self, val):
-        super(MultiValue, self).append(self.type_constructor(val))
-
-    def __deepcopy__(self, memo):
-        return MultiValue(self.type_constructor, self)
-
-    def extend(self, list_of_vals):
-        super(MultiValue, self).extend((self.type_constructor(x)
-                                        for x in list_of_vals))
+        self._list = list()
+        self.type_constructor = type_constructor
+        if type_constructor in (DSfloat, IS, DSdecimal):
+            type_constructor = number_string_type_constructor
+        for x in iterable:
+            self._list.append(type_constructor(x))
 
     def insert(self, position, val):
-        super(MultiValue, self).insert(position, self.type_constructor(val))
+        self._list.insert(position, self.type_constructor(val))
 
     def __setitem__(self, i, val):
         """Set an item of the list, making sure it is of the right VR type"""
         if isinstance(i, slice):
-            val = [self.type_constructor(x) for x in val]
+            val = [self.type_constructor(v) for v in val]
+            self._list.__setitem__(i, val)
         else:
-            val = self.type_constructor(val)
-        super(MultiValue, self).__setitem__(i, val)
+            self._list.__setitem__(i, self.type_constructor(val))
 
     def __str__(self):
         lines = [str(x) for x in self]
         return "['" + "', '".join(lines) + "']"
 
     __repr__ = __str__
+
+    def __len__(self):
+        return len(self._list)
+
+    def __getitem__(self, index):
+        return self._list[index]
+
+    def __delitem__(self, index):
+        del self._list[index]
+
+    def __iter__(self):
+        return iter(self._list)
+
+    def __eq__(self, other):
+        return self._list == other
diff --git a/setup.py b/setup.py
index ae1d69e28..a570e76d3 100755
--- a/setup.py
+++ b/setup.py
@@ -1,7 +1,10 @@
 #!/usr/bin/env python
+
+import os
+from glob import glob
 from setuptools import setup, find_packages
-from pydicom import __version__
 
+from pydicom import __version__
 
 description = "Pure python package for DICOM medical file reading and writing"
 
@@ -52,9 +55,22 @@ URL = "https://github.com/pydicom/pydicom"
 DOWNLOAD_URL = "https://github.com/pydicom/pydicom/archive/master.zip"
 LICENSE = "MIT"
 VERSION = __version__
-PACKAGE_DATA = {'pydicom': ['tests/test_files/*', 'tests/charset_files/*']}
 REQUIRES = []
 
+
+def data_files_inventory():
+    data_files = []
+    data_roots = ['pydicom/data']
+    for data_root in data_roots:
+        for root, subfolder, files in os.walk(data_root):
+            files = [x.replace('pydicom/', '') for x in glob(root + '/*')
+                     if not os.path.isdir(x)]
+            data_files = data_files + files
+    return data_files
+
+
+PACKAGE_DATA = {'pydicom': data_files_inventory()}
+
 opts = dict(name=NAME,
             version=__version__,
             maintainer=MAINTAINER,


Test patch:
diff --git a/pydicom/tests/test_JPEG_LS_transfer_syntax.py b/pydicom/tests/test_JPEG_LS_transfer_syntax.py
index a6b164a2c..a069ae9d3 100644
--- a/pydicom/tests/test_JPEG_LS_transfer_syntax.py
+++ b/pydicom/tests/test_JPEG_LS_transfer_syntax.py
@@ -4,6 +4,7 @@ import re
 import pytest
 import pydicom
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 pillow_missing_message = ("pillow is not available "
                           "in this test environment")
 pillow_present_message = "pillow is being tested"
@@ -39,8 +40,7 @@ try:
 except ImportError:
     gdcm_handler = None
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 mr_name = os.path.join(test_files, "MR_small.dcm")
 jpeg_ls_lossless_name = os.path.join(
diff --git a/pydicom/tests/test_RLE_transfer_syntax.py b/pydicom/tests/test_RLE_transfer_syntax.py
index 020cb0af2..0004cc6bf 100644
--- a/pydicom/tests/test_RLE_transfer_syntax.py
+++ b/pydicom/tests/test_RLE_transfer_syntax.py
@@ -4,6 +4,7 @@ import re
 import pytest
 import pydicom
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 pillow_missing_message = ("pillow is not available "
                           "in this test environment")
 pillow_present_message = "pillow is being tested"
@@ -39,8 +40,7 @@ try:
 except ImportError:
     gdcm_handler = None
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 mr_name = os.path.join(test_files, "MR_small.dcm")
 compressed_mr_name = os.path.join(
diff --git a/pydicom/tests/test_charset.py b/pydicom/tests/test_charset.py
index e54f516c8..2396920dc 100644
--- a/pydicom/tests/test_charset.py
+++ b/pydicom/tests/test_charset.py
@@ -7,20 +7,19 @@
 #    available at https://github.com/pydicom/pydicom
 
 import unittest
+from pydicom.data import DATA_ROOT
 from pydicom import dicomio
 import os.path
 import pydicom.charset
 
-test_dir = os.path.dirname(__file__)
-testcharset_dir = os.path.join(test_dir, 'charset_files')
+testcharset_dir = os.path.join(DATA_ROOT, 'charset_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 latin1_file = os.path.join(testcharset_dir, "chrFren.dcm")
 jp_file = os.path.join(testcharset_dir, "chrH31.dcm")
 multiPN_file = os.path.join(testcharset_dir, "chrFrenMulti.dcm")
 sq_encoding_file = os.path.join(testcharset_dir, "chrSQEncoding.dcm")
 explicit_ir6_file = os.path.join(testcharset_dir, "chrJapMultiExplicitIR6.dcm")
-
-test_files = os.path.join(test_dir, 'test_files')
 normal_file = os.path.join(test_files, "CT_small.dcm")
 
 
diff --git a/pydicom/tests/test_dataelem.py b/pydicom/tests/test_dataelem.py
index 2fbc4709d..56d0c49d4 100644
--- a/pydicom/tests/test_dataelem.py
+++ b/pydicom/tests/test_dataelem.py
@@ -11,6 +11,8 @@ import unittest
 
 import sys
 
+from pydicom.valuerep import DSfloat
+
 from pydicom.charset import default_encoding
 
 from pydicom.dataelem import DataElement
@@ -43,6 +45,26 @@ class DataElementTests(unittest.TestCase):
         self.assertEqual(VM, 1,
                          "Wrong Value Multiplicity, expected 1, got %i" % VM)
 
+    def testDSFloatConversion(self):
+        """Test that strings are correctly converted if changing the value."""
+        self.assertTrue(isinstance(self.data_elementDS.value, DSfloat))
+        self.assertTrue(isinstance(self.data_elementMulti.value[0], DSfloat))
+        self.assertEqual(DSfloat('42.1'), self.data_elementMulti.value[0])
+
+        # multi-value append/insert
+        self.data_elementMulti.value.append('42.4')
+        self.assertTrue(isinstance(self.data_elementMulti.value[3], DSfloat))
+        self.assertEqual(DSfloat('42.4'), self.data_elementMulti.value[3])
+
+        self.data_elementMulti.value.insert(0, '42.0')
+        self.assertTrue(isinstance(self.data_elementMulti.value[0], DSfloat))
+        self.assertEqual(DSfloat('42.0'), self.data_elementMulti.value[0])
+
+        # change single value of multi-value
+        self.data_elementMulti.value[3] = '123.4'
+        self.assertTrue(isinstance(self.data_elementMulti.value[3], DSfloat))
+        self.assertEqual(DSfloat('123.4'), self.data_elementMulti.value[3])
+
     def testBackslash(self):
         """DataElement: String with '\\' sets multi-valued data_element."""
         data_element = DataElement((1, 2), "DS", r"42.1\42.2\42.3")
diff --git a/pydicom/tests/test_dataset.py b/pydicom/tests/test_dataset.py
index 9d8a200c7..01dfa0453 100644
--- a/pydicom/tests/test_dataset.py
+++ b/pydicom/tests/test_dataset.py
@@ -1,20 +1,27 @@
-# test_dataset.py
+# Copyright 2008-2017 pydicom authors. See LICENSE file for details.
 """unittest cases for pydicom.dataset module"""
-# Copyright (c) 2008-2012 Darcy Mason
-# This file is part of pydicom, released under a modified MIT license.
-#    See the file license.txt included with this distribution, also
-#    available at https://github.com/darcymason/pydicom
 
 import os
 import unittest
 
-from pydicom.dataset import Dataset
+import pytest
+
+from pydicom import compat
+from pydicom.data import DATA_ROOT
 from pydicom.dataelem import DataElement, RawDataElement
+from pydicom.dataset import Dataset, FileDataset
 from pydicom.dicomio import read_file
 from pydicom.filebase import DicomBytesIO
-from pydicom.tag import Tag
 from pydicom.sequence import Sequence
-from pydicom import compat
+from pydicom.tag import Tag
+from pydicom.uid import ImplicitVRLittleEndian, JPEGBaseLineLossy8bit
+
+
+def assert_raises_regex(type_error, message, func, *args, **kwargs):
+    """Taken from https://github.com/glemaitre/specio, BSD 3 license."""
+    with pytest.raises(type_error) as excinfo:
+        func(*args, **kwargs)
+    excinfo.match(message)
 
 
 class DatasetTests(unittest.TestCase):
@@ -166,17 +173,19 @@ class DatasetTests(unittest.TestCase):
         self.assertTrue(
             'Dummyname' not in ds, "non-member tested as member")
 
-    def testContains(self):
+    def test_contains(self):
         """Dataset: can test if item present by 'if <tag> in dataset'......."""
         ds = self.dummy_dataset()
         ds.CommandGroupLength = 100  # (0000,0000)
-        self.assertTrue((0x300a, 0xb2) in ds, "membership test failed")
-        self.assertTrue([0x300a, 0xb2] in ds,
-                        "membership test failed when list used")
-        self.assertTrue(0x300a00b2 in ds, "membership test failed")
-        self.assertTrue(
-            (0x10, 0x5f) not in ds, "non-member tested as member")
-        self.assertTrue('CommandGroupLength' in ds)
+        assert (0x300a, 0xb2) in ds
+        assert [0x300a, 0xb2] in ds
+        assert 0x300a00b2 in ds
+        assert (0x10, 0x5f) not in ds
+        assert 'CommandGroupLength' in ds
+        # Use a negative tag to cause an exception
+        assert (-0x0010, 0x0010) not in ds
+        # Random non-existent property
+        assert 'random name' not in ds
 
     def testGetExists1(self):
         """Dataset: dataset.get() returns an existing item by name.........."""
@@ -247,6 +256,13 @@ class DatasetTests(unittest.TestCase):
                " for non-member by Tag")
         self.assertEqual(not_there, "not-there", msg)
 
+    def test_get_raises(self):
+        """Test Dataset.get() raises exception when invalid Tag"""
+        ds = self.dummy_dataset()
+        assert_raises_regex(TypeError,
+                            'Dataset.get key must be a string or tag',
+                            ds.get, (-0x0010, 0x0010))
+
     def testGetFromRaw(self):
         """Dataset: get(tag) returns same object as ds[tag] for raw element."""
         # This came from issue 88, where get(tag#) returned a RawDataElement,
@@ -299,8 +315,8 @@ class DatasetTests(unittest.TestCase):
             'Johnny',
             "set by tag failed")
 
-    def testDir(self):
-        """Dataset: dir() returns sorted list of named data_elements........"""
+    def test_dir(self):
+        """Dataset.dir() returns sorted list of named data_elements."""
         ds = self.dummy_dataset()
         ds.PatientName = "name"
         ds.PatientID = "id"
@@ -311,11 +327,25 @@ class DatasetTests(unittest.TestCase):
                     'PatientName',
                     'TreatmentMachineName',
                     'XRayTubeCurrent']
-        self.assertEqual(
-            ds.dir(),
-            expected,
-            "dir() returned %s, "
-            "expected %s" % (str(ds.dir()), str(expected)))
+        assert ds.dir() == expected
+
+    def test_dir_filter(self):
+        """Test Dataset.dir(*filters) works OK."""
+        ds = self.dummy_dataset()
+        ds.PatientName = "name"
+        ds.PatientID = "id"
+        ds.NonDicomVariable = "junk"
+        ds.add_new((0x18, 0x1151), "IS", 150)  # X-ray Tube Current
+        ds.add_new((0x1111, 0x123), "DS", "42.0")  # private - no name in dir()
+        assert 'PatientID' in ds
+        assert 'XRayTubeCurrent' in ds
+        assert 'TreatmentMachineName' in ds
+        assert 'PatientName' in ds
+        assert 'PatientBirthDate' not in ds
+        assert ds.dir('Patient') == ['PatientID', 'PatientName']
+        assert ds.dir('Name') == ['PatientName', 'TreatmentMachineName']
+        assert ds.dir('Name', 'Patient') == ['PatientID', 'PatientName',
+                                             'TreatmentMachineName']
 
     def testDeleteDicomAttr(self):
         """Dataset: delete DICOM attribute by name.........................."""
@@ -706,16 +736,22 @@ class DatasetTests(unittest.TestCase):
 
     def test_get_item(self):
         """Test Dataset.get_item"""
-        # TODO: Add test for deferred read
         ds = Dataset()
         ds.CommandGroupLength = 120  # 0000,0000
         ds.SOPInstanceUID = '1.2.3.4'  # 0008,0018
 
         # Test non-deferred read
-        self.assertEqual(ds.get_item(0x00000000), ds[0x00000000])
-        self.assertEqual(ds.get_item(0x00000000).value, 120)
-        self.assertEqual(ds.get_item(0x00080018), ds[0x00080018])
-        self.assertEqual(ds.get_item(0x00080018).value, '1.2.3.4')
+        assert ds.get_item(0x00000000) == ds[0x00000000]
+        assert ds.get_item(0x00000000).value == 120
+        assert ds.get_item(0x00080018) == ds[0x00080018]
+        assert ds.get_item(0x00080018).value == '1.2.3.4'
+
+        # Test deferred read
+        test_file = os.path.join(DATA_ROOT, 'test_files', 'MR_small.dcm')
+        ds = read_file(test_file, force=True, defer_size='0.8 kB')
+        ds_ref = read_file(test_file, force=True)
+        # get_item will follow the deferred read branch
+        assert ds.get_item((0x7fe00010)).value == ds_ref.PixelData
 
     def test_remove_private_tags(self):
         """Test Dataset.remove_private_tags"""
@@ -740,10 +776,9 @@ class DatasetTests(unittest.TestCase):
         ds.add_new(0x00090001, 'PN', 'CITIZEN^1')
         ds.BeamSequence = [Dataset()]
         ds.BeamSequence[0].PatientName = 'ANON'
-        self.assertEqual(
-            ds.data_element('CommandGroupLength'), ds[0x00000000])
-        self.assertEqual(
-            ds.data_element('BeamSequence'), ds[0x300A00B0])
+        assert ds.data_element('CommandGroupLength') == ds[0x00000000]
+        assert ds.data_element('BeamSequence') == ds[0x300A00B0]
+        assert ds.data_element('not an element keyword') is None
 
     def test_iterall(self):
         """Test Dataset.iterall"""
@@ -797,6 +832,121 @@ class DatasetTests(unittest.TestCase):
         ds.file_meta.ImplementationClassUID = '1.4'
         ds.save_as(fp, write_like_original=False)
 
+    def test_with(self):
+        """Test Dataset.__enter__ and __exit__."""
+        test_file = os.path.join(DATA_ROOT, 'test_files', 'CT_small.dcm')
+        with read_file(test_file) as ds:
+            assert ds.PatientName == 'CompressedSamples^CT1'
+
+    def test_exit_exception(self):
+        """Test Dataset.__exit__ when an exception is raised."""
+        class DSException(Dataset):
+            @property
+            def test(self):
+                raise ValueError("Random ex message!")
+
+        assert_raises_regex(ValueError,
+                            "Random ex message!",
+                            getattr, DSException(), 'test')
+
+    def test_is_uncompressed_transfer_syntax(self):
+        """Test Dataset._is_uncompressed_transfer_syntax"""
+        ds = Dataset()
+        with pytest.raises(AttributeError):
+            ds._is_uncompressed_transfer_syntax()
+        ds.file_meta = Dataset()
+        with pytest.raises(AttributeError):
+            ds._is_uncompressed_transfer_syntax()
+        ds.file_meta.TransferSyntaxUID = ImplicitVRLittleEndian
+        assert ds._is_uncompressed_transfer_syntax()
+        ds.file_meta.TransferSyntaxUID = JPEGBaseLineLossy8bit
+        assert not ds._is_uncompressed_transfer_syntax()
+
+    def test_reshape_pixel_array_not_implemented(self):
+        """Test Dataset._reshape_pixel_array raises exception"""
+        ds = Dataset()
+        ds.SamplesPerPixel = 2
+        ds.BitsAllocated = 16
+        with pytest.raises(NotImplementedError):
+            ds._reshape_pixel_array(None)
+
+    def test_get_pixel_array_already_have(self):
+        """Test Dataset._get_pixel_array when we already have the array"""
+        # Test that _pixel_array is returned unchanged unless required
+        ds = Dataset()
+        ds.PixelData = b'\x00'
+        ds._pixel_id = id(ds.PixelData)
+        ds._pixel_array = 'Test Value'
+        assert ds._get_pixel_array() == 'Test Value'
+
+    def test_formatted_lines(self):
+        """Test Dataset.formatted_lines"""
+        ds = Dataset()
+        ds.PatientName = 'CITIZEN^Jan'
+        ds.BeamSequence = [Dataset()]
+        ds.BeamSequence[0].PatientID = 'JAN^Citizen'
+        elem_format = "%(tag)s"
+        seq_format = "%(name)s %(tag)s"
+        indent_format = ">>>"  # placeholder for future functionality
+
+        line_generator = ds.formatted_lines(element_format=elem_format,
+                                            sequence_element_format=seq_format,
+                                            indent_format=indent_format)
+        assert next(line_generator) == "(0010, 0010)"
+        assert next(line_generator) == "Beam Sequence (300a, 00b0)"
+        assert next(line_generator) == "(0010, 0020)"
+
+    def test_set_convert_private_elem_from_raw(self):
+        """Test Dataset.__setitem__ with a raw private element"""
+        test_file = os.path.join(DATA_ROOT, 'test_files', 'CT_small.dcm')
+        ds = read_file(test_file, force=True)
+        # 'tag VR length value value_tell is_implicit_VR is_little_endian'
+        elem = RawDataElement((0x0043, 0x1029), 'OB', 2, b'\x00\x01', 0,
+                              True, True)
+        ds.__setitem__((0x0043, 0x1029), elem)
+
+        assert ds[(0x0043, 0x1029)].value == b'\x00\x01'
+        assert type(ds[(0x0043, 0x1029)]) == DataElement
+
+    def test_top(self):
+        """Test Dataset.top returns only top level str"""
+        ds = Dataset()
+        ds.PatientName = 'CITIZEN^Jan'
+        ds.BeamSequence = [Dataset()]
+        ds.BeamSequence[0].PatientID = 'JAN^Citizen'
+        assert "Patient's Name" in ds.top()
+        assert "Patient ID" not in ds.top()
+
+    def test_trait_names(self):
+        """Test Dataset.trait_names contains element keywords"""
+        test_file = os.path.join(DATA_ROOT, 'test_files', 'CT_small.dcm')
+        ds = read_file(test_file, force=True)
+        names = ds.trait_names()
+        assert 'PatientName' in names
+        assert 'save_as' in names
+        assert 'PixelData' in names
+
+    def test_walk(self):
+        """Test Dataset.walk iterates through sequences"""
+        def test_callback(dataset, elem):
+            if elem.keyword is 'PatientID':
+                dataset.PatientID = 'FIXED'
+
+        ds = Dataset()
+        ds.PatientName = 'CITIZEN^Jan'
+        ds.BeamSequence = [Dataset(), Dataset()]
+        ds.BeamSequence[0].PatientID = 'JAN^Citizen^Snr'
+        ds.BeamSequence[0].PatientName = 'Some^Name'
+        ds.BeamSequence[1].PatientID = 'JAN^Citizen^Jr'
+        ds.BeamSequence[1].PatientName = 'Other^Name'
+        ds.walk(test_callback, recursive=True)
+
+        assert ds.PatientName == 'CITIZEN^Jan'
+        assert ds.BeamSequence[0].PatientID == 'FIXED'
+        assert ds.BeamSequence[0].PatientName == 'Some^Name'
+        assert ds.BeamSequence[1].PatientID == 'FIXED'
+        assert ds.BeamSequence[1].PatientName == 'Other^Name'
+
 
 class DatasetElementsTests(unittest.TestCase):
     """Test valid assignments of data elements"""
@@ -821,10 +971,11 @@ class DatasetElementsTests(unittest.TestCase):
 
 class FileDatasetTests(unittest.TestCase):
     def setUp(self):
-        test_dir = os.path.dirname(__file__)
-        self.test_file = os.path.join(test_dir, 'test_files', 'CT_small.dcm')
+        self.test_file = os.path.join(DATA_ROOT,
+                                      'test_files',
+                                      'CT_small.dcm')
 
-    def testEqualityFileMeta(self):
+    def test_equality_file_meta(self):
         """Dataset: equality returns correct value if with metadata"""
         d = read_file(self.test_file)
         e = read_file(self.test_file)
@@ -843,6 +994,16 @@ class FileDatasetTests(unittest.TestCase):
         e.filename = 'test_filename.dcm'
         self.assertFalse(d == e)
 
+    def test_creation_with_container(self):
+        """FileDataset.__init__ works OK with a container such as gzip"""
+        class Dummy(object):
+            filename = '/some/path/to/test'
+
+        ds = Dataset()
+        ds.PatientName = "CITIZEN^Jan"
+        fds = FileDataset(Dummy(), ds)
+        assert fds.filename == '/some/path/to/test'
+
 
 if __name__ == "__main__":
     unittest.main()
diff --git a/pydicom/tests/test_filereader.py b/pydicom/tests/test_filereader.py
index 9a399db03..c670b9882 100644
--- a/pydicom/tests/test_filereader.py
+++ b/pydicom/tests/test_filereader.py
@@ -14,10 +14,13 @@ import shutil
 import sys
 import tempfile
 import unittest
+
+from pydicom.filebase import DicomBytesIO
 from pydicom.util.testing.warncheck import assertWarns
 from pydicom.dataset import Dataset, FileDataset
+from pydicom.data import DATA_ROOT
 from pydicom.dataelem import DataElement
-from pydicom.filereader import read_file
+from pydicom.filereader import read_file, data_element_generator
 from pydicom.errors import InvalidDicomError
 from pydicom.tag import Tag, TupleTag
 from pydicom.uid import ImplicitVRLittleEndian
@@ -66,8 +69,7 @@ have_numpy = numpy is not None
 have_jpeg_ls = jpeg_ls is not None
 have_pillow = PILImg is not None
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 empty_number_tags_name = os.path.join(test_files,
                                       "reportsi_with_empty_number_tags.dcm")
@@ -668,6 +670,22 @@ class ReaderTests(unittest.TestCase):
         self.assertEqual(ds.file_meta, Dataset())
         self.assertEqual(ds[:], Dataset())
 
+    def test_read_file_does_not_raise(self):
+        """Test that reading from DicomBytesIO does not raise on EOF.
+        Regression test for #358."""
+        ds = read_file(mr_name)
+        fp = DicomBytesIO()
+        ds.save_as(fp)
+        fp.seek(0)
+        de_gen = data_element_generator(fp, False, True)
+        try:
+            while True:
+                next(de_gen)
+        except StopIteration:
+            pass
+        except EOFError:
+            self.fail('Unexpected EOFError raised')
+
 
 class ReadDataElementTests(unittest.TestCase):
     def setUp(self):
diff --git a/pydicom/tests/test_filewriter.py b/pydicom/tests/test_filewriter.py
index fb774dcc7..9be6fc6ea 100644
--- a/pydicom/tests/test_filewriter.py
+++ b/pydicom/tests/test_filewriter.py
@@ -1,9 +1,5 @@
-# test_filewriter.py
+# Copyright 2008-2017 pydicom authors. See LICENSE file for details.
 """unittest cases for pydicom.filewriter module"""
-# Copyright (c) 2008-2012 Darcy Mason
-# This file is part of pydicom, released under a modified MIT license.
-#    See the file license.txt included with this distribution, also
-#    available at https://github.com/darcymason/pydicom
 
 from copy import deepcopy
 from datetime import date, datetime, time
@@ -13,12 +9,12 @@ import os.path
 from struct import unpack
 import sys
 from tempfile import TemporaryFile
-import unittest
 
 import pytest
 
 from pydicom._storage_sopclass_uids import CTImageStorage
 from pydicom import config, __version__
+from pydicom.data import DATA_ROOT
 from pydicom.dataset import Dataset, FileDataset
 from pydicom.dataelem import DataElement
 from pydicom.filebase import DicomBytesIO
@@ -31,16 +27,24 @@ from pydicom.uid import (ImplicitVRLittleEndian, ExplicitVRBigEndian,
                          PYDICOM_IMPLEMENTATION_UID)
 from pydicom.util.hexutil import hex2bytes, bytes2hex
 from pydicom.valuerep import DA, DT, TM
+import unittest
 
 have_dateutil = True
 try:
     from dateutil.tz import tzoffset
 except ImportError:
     have_dateutil = False
+try:
+    unittest.TestCase.assertSequenceEqual
+except AttributeError:
+    try:
+        import unittest2 as unittest
+    except ImportError:
+        print("unittest2 is required for testing in python2.6")
+
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
-testcharset_dir = os.path.join(test_dir, 'charset_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
+testcharset_dir = os.path.join(DATA_ROOT, 'charset_files')
 
 rtplan_name = os.path.join(test_files, "rtplan.dcm")
 rtdose_name = os.path.join(test_files, "rtdose.dcm")
@@ -65,16 +69,17 @@ def files_identical(a, b):
 
 
 def bytes_identical(a_bytes, b_bytes):
-    """Return a tuple (bytes a == bytes b, index of first difference)"""
+    """Return a tuple
+       (bytes a == bytes b, index of first difference)"""
     if len(a_bytes) != len(b_bytes):
         return False, min([len(a_bytes), len(b_bytes)])
     elif a_bytes == b_bytes:
-        return True, 0     # True, dummy argument
+        return True, 0  # True, dummy argument
     else:
         pos = 0
         while a_bytes[pos] == b_bytes[pos]:
             pos += 1
-        return False, pos   # False if not identical, position of 1st diff
+        return False, pos  # False if not identical, position of 1st diff
 
 
 class WriteFileTests(unittest.TestCase):
@@ -82,7 +87,8 @@ class WriteFileTests(unittest.TestCase):
         self.file_out = TemporaryFile('w+b')
 
     def compare(self, in_filename, decode=False):
-        """Read Dataset from `in_filename`, write to file, then compare."""
+        """Read Dataset from in_filename, write to file, compare"""
+
         with open(in_filename, 'rb') as f:
             bytes_in = BytesIO(f.read())
             bytes_in.seek(0)
@@ -104,35 +110,43 @@ class WriteFileTests(unittest.TestCase):
                         "difference at 0x%x" % pos)
 
     def testRTPlan(self):
-        """Input file, write back and verify them identical (RT Plan file)"""
+        """Input file, write back and verify
+           them identical (RT Plan file)"""
         self.compare(rtplan_name)
 
     def testRTDose(self):
-        """Input file, write back and verify them identical (RT Dose file)"""
+        """Input file, write back and
+           verify them identical (RT Dose file)"""
         self.compare(rtdose_name)
 
     def testCT(self):
-        """Input file, write back and verify them identical (CT file)....."""
+        """Input file, write back and
+           verify them identical (CT file)....."""
         self.compare(ct_name)
 
     def testMR(self):
-        """Input file, write back and verify them identical (MR file)....."""
+        """Input file, write back and verify
+           them identical (MR file)....."""
         self.compare(mr_name)
 
     def testUnicode(self):
-        """Ensure decoded string DataElements are written to file properly"""
+        """Ensure decoded string DataElements
+           are written to file properly"""
         self.compare(unicode_name, decode=True)
 
     def testMultiPN(self):
-        """Ensure multiple Person Names are written to the file correctly."""
+        """Ensure multiple Person Names are written
+           to the file correctly."""
         self.compare(multiPN_name, decode=True)
 
     def testJPEG2000(self):
-        """Input file, write back and verify them identical (JPEG2K file)."""
+        """Input file, write back and verify
+           them identical (JPEG2K file)."""
         self.compare(jpeg_name)
 
     def testListItemWriteBack(self):
-        """Change item in a list and confirm it is written to file      .."""
+        """Change item in a list and confirm
+          it is written to file"""
         DS_expected = 0
         CS_expected = "new"
         SS_expected = 999
@@ -208,6 +222,7 @@ class ScratchWriteDateTimeTests(WriteFileTests):
         self.file_out.seek(0)
         # Now read it back in and check the values are as expected
         ds = read_file(self.file_out)
+
         self.assertSequenceEqual(multi_DA_expected, ds.CalibrationDate)
         self.assertEqual(DA_expected, ds.DateOfLastCalibration)
         self.assertSequenceEqual(multi_DT_expected, ds.ReferencedDateTime)
@@ -259,10 +274,71 @@ class WriteDataElementTests(unittest.TestCase):
         got = self.f1.getvalue()
         msg = ("Did not write zero-length AT value correctly. "
                "Expected %r, got %r") % (bytes2hex(expected), bytes2hex(got))
-        msg = "%r %r" % (type(expected), type(got))
-        msg = "'%r' '%r'" % (expected, got)
         self.assertEqual(expected, got, msg)
 
+    def check_data_element(self, data_elem, expected):
+        encoded_elem = self.encode_element(data_elem)
+        self.assertEqual(expected, encoded_elem)
+
+    def test_write_DA(self):
+        data_elem = DataElement(0x00080022, 'DA', '20000101')
+        expected = (b'\x08\x00\x22\x00'  # tag
+                    b'\x08\x00\x00\x00'  # length
+                    b'20000101')  # value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x00080022, 'DA', date(2000, 1, 1))
+        self.check_data_element(data_elem, expected)
+
+    def test_write_multi_DA(self):
+        data_elem = DataElement(0x0014407E, 'DA', ['20100101', '20101231'])
+        expected = (b'\x14\x00\x7E\x40'  # tag
+                    b'\x12\x00\x00\x00'  # length
+                    b'20100101\\20101231 ')  # padded value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x0014407E, 'DA', [date(2010, 1, 1),
+                                                   date(2010, 12, 31)])
+        self.check_data_element(data_elem, expected)
+
+    def test_write_TM(self):
+        data_elem = DataElement(0x00080030, 'TM', '010203')
+        expected = (b'\x08\x00\x30\x00'  # tag
+                    b'\x06\x00\x00\x00'  # length
+                    b'010203')  # padded value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x00080030, 'TM', time(1, 2, 3))
+        self.check_data_element(data_elem, expected)
+
+    def test_write_multi_TM(self):
+        data_elem = DataElement(0x0014407C, 'TM', ['082500', '092655'])
+        expected = (b'\x14\x00\x7C\x40'  # tag
+                    b'\x0E\x00\x00\x00'  # length
+                    b'082500\\092655 ')  # padded value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x0014407C, 'TM', [time(8, 25),
+                                                   time(9, 26, 55)])
+        self.check_data_element(data_elem, expected)
+
+    def test_write_DT(self):
+        data_elem = DataElement(0x0008002A, 'DT', '20170101120000')
+        expected = (b'\x08\x00\x2A\x00'  # tag
+                    b'\x0E\x00\x00\x00'  # length
+                    b'20170101120000')  # value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x0008002A, 'DT', datetime(2017, 1, 1, 12))
+        self.check_data_element(data_elem, expected)
+
+    def test_write_multi_DT(self):
+        data_elem = DataElement(0x0040A13A, 'DT',
+                                ['20120820120804', '20130901111111'])
+        expected = (b'\x40\x00\x3A\xA1'  # tag
+                    b'\x1E\x00\x00\x00'  # length
+                    b'20120820120804\\20130901111111 ')  # padded value
+        self.check_data_element(data_elem, expected)
+        data_elem = DataElement(0x0040A13A, 'DT',
+                                [datetime(2012, 8, 20, 12, 8, 4),
+                                 datetime(2013, 9, 1, 11, 11, 11)])
+        self.check_data_element(data_elem, expected)
+
     def test_write_OD_implicit_little(self):
         """Test writing elements with VR of OD works correctly."""
         # VolumetricCurvePoints
@@ -297,10 +373,12 @@ class WriteDataElementTests(unittest.TestCase):
         # VR (OD): \x4f\x44
         # Reserved: \x00\x00
         # Length (16): \x10\x00\x00\x00
+
         #             | Tag          | VR    |
         ref_bytes = b'\x70\x00\x0d\x15\x4f\x44' \
                     b'\x00\x00\x10\x00\x00\x00' + bytestring
         #             |Rsrvd |   Length      |    Value ->
+
         self.assertEqual(encoded_elem, ref_bytes)
 
         # Empty data
@@ -343,10 +421,12 @@ class WriteDataElementTests(unittest.TestCase):
         # VR (OL): \x4f\x4c
         # Reserved: \x00\x00
         # Length (12): 0c 00 00 00
+
         #             | Tag          | VR    |
         ref_bytes = b'\x66\x00\x29\x01\x4f\x4c' \
                     b'\x00\x00\x0c\x00\x00\x00' + bytestring
         #             |Rsrvd |   Length      |    Value ->
+
         self.assertEqual(encoded_elem, ref_bytes)
 
         # Empty data
@@ -465,7 +545,8 @@ class WriteDataElementTests(unittest.TestCase):
         # Empty value
         elem.value = ''
         encoded_elem = self.encode_element(elem)
-        self.assertEqual(encoded_elem, b'\x08\x00\x20\x01\x00\x00\x00\x00')
+        self.assertEqual(encoded_elem,
+                         b'\x08\x00\x20\x01\x00\x00\x00\x00')
 
     def test_write_UR_explicit_little(self):
         """Test writing elements with VR of UR works correctly.
@@ -692,6 +773,7 @@ class TestCorrectAmbiguousVR(unittest.TestCase):
         ref_ds.BeamSequence[0].PixelRepresentation = 0
         ref_ds.BeamSequence[0].SmallestValidPixelValue = b'\x00\x01'
         ref_ds.BeamSequence[0].BeamSequence = [Dataset()]
+
         ref_ds.BeamSequence[0].BeamSequence[0].PixelRepresentation = 0
         ref_ds.BeamSequence[0].BeamSequence[0].SmallestValidPixelValue = \
             b'\x00\x01'
@@ -799,87 +881,91 @@ class ScratchWriteTests(unittest.TestCase):
         # print "std    :", bytes2hex(std)
         # print "written:", bytes2hex(bytes_written)
         same, pos = bytes_identical(std, bytes_written)
+
         self.assertTrue(same,
                         "Writing from scratch unexpected result "
                         "- 1st diff at 0x%x" % pos)
+
         if os.path.exists(out_filename):
             os.remove(out_filename)  # get rid of the file
 
     def testImpl_LE_deflen_write(self):
-        """Scratch Write for implicit VR little endian, defined length SQ's"""
+        """Scratch Write for implicit VR little endian, defined length SQs"""
         from pydicom.util.testing._write_stds import impl_LE_deflen_std_hex
-
         file_ds = FileDataset("test", self.ds)
         self.compare_write(impl_LE_deflen_std_hex, file_ds)
 
 
-class TestWriteToStandard(unittest.TestCase):
+class TestWriteToStandard(object):
     """Unit tests for writing datasets to the DICOM standard"""
-    def setUp(self):
-        """Create an empty file-like for use in testing."""
-        self.fp = BytesIO()
-
     def test_preamble_default(self):
         """Test that the default preamble is written correctly when present."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         ds.preamble = b'\x00' * 128
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        self.assertEqual(self.fp.read(128), b'\x00' * 128)
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == b'\x00' * 128
 
     def test_preamble_custom(self):
         """Test that a custom preamble is written correctly when present."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         ds.preamble = b'\x01\x02\x03\x04' + b'\x00' * 124
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        assert self.fp.read(128) == b'\x01\x02\x03\x04' + b'\x00' * 124
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == b'\x01\x02\x03\x04' + b'\x00' * 124
 
     def test_no_preamble(self):
         """Test that a default preamble is written when absent."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         del ds.preamble
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        self.assertEqual(self.fp.read(128), b'\x00' * 128)
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == b'\x00' * 128
 
     def test_none_preamble(self):
         """Test that a default preamble is written when None."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         ds.preamble = None
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        self.assertEqual(self.fp.read(128), b'\x00' * 128)
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == b'\x00' * 128
 
     def test_bad_preamble(self):
         """Test that ValueError is raised when preamble is bad."""
         ds = read_file(ct_name)
         ds.preamble = b'\x00' * 127
         with pytest.raises(ValueError):
-            ds.save_as(self.fp, write_like_original=False)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
         ds.preamble = b'\x00' * 129
         with pytest.raises(ValueError):
-            ds.save_as(self.fp, write_like_original=False)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
 
     def test_prefix(self):
-        """Test that the 'DICM' prefix is written with preamble."""
+        """Test that the 'DICM' prefix
+           is written with preamble."""
         # Has preamble
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         ds.preamble = b'\x00' * 128
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(128)
-        self.assertEqual(self.fp.read(4), b'DICM')
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(128)
+        assert fp.read(4) == b'DICM'
 
     def test_prefix_none(self):
         """Test the 'DICM' prefix is written when preamble is None"""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         ds.preamble = None
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(128)
-        self.assertEqual(self.fp.read(4), b'DICM')
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(128)
+        assert fp.read(4) == b'DICM'
 
-    def test_ds_unchanged(self):
-        """Test writing the dataset doesn't change it."""
+    def test_ds_changed(self):
+        """Test writing the dataset changes its file_meta."""
         ds = read_file(rtplan_name)
         ref_ds = read_file(rtplan_name)
         # Ensure no RawDataElements in ref_ds
@@ -887,9 +973,15 @@ class TestWriteToStandard(unittest.TestCase):
             pass
         for elem in ref_ds.iterall():
             pass
-        ds.save_as(self.fp, write_like_original=False)
-        self.assertTrue(ref_ds.file_meta == ds.file_meta)
-        self.assertTrue(ref_ds == ds)
+
+        for ref_elem, test_elem in zip(ref_ds.file_meta, ds.file_meta):
+            assert ref_elem == test_elem
+
+        ds.save_as(DicomBytesIO(), write_like_original=False)
+        assert ref_ds.file_meta != ds.file_meta
+        del ref_ds.file_meta
+        del ds.file_meta
+        assert ref_ds == ds
 
     def test_transfer_syntax_added(self):
         """Test TransferSyntaxUID is added/updated if possible."""
@@ -898,13 +990,13 @@ class TestWriteToStandard(unittest.TestCase):
         ds = read_file(rtplan_name)
         ds.is_implicit_VR = True
         ds.is_little_endian = True
-        ds.save_as(self.fp, write_like_original=False)
+        ds.save_as(DicomBytesIO(), write_like_original=False)
         assert ds.file_meta.TransferSyntaxUID == ImplicitVRLittleEndian
 
         # Updated
         ds.is_implicit_VR = False
         ds.is_little_endian = False
-        ds.save_as(self.fp, write_like_original=False)
+        ds.save_as(DicomBytesIO(), write_like_original=False)
         assert ds.file_meta.TransferSyntaxUID == ExplicitVRBigEndian
 
     def test_transfer_syntax_not_added(self):
@@ -913,165 +1005,276 @@ class TestWriteToStandard(unittest.TestCase):
         del ds.file_meta.TransferSyntaxUID
         ds.is_implicit_VR = False
         ds.is_little_endian = True
+
         with pytest.raises(ValueError):
-            ds.save_as(self.fp, write_like_original=False)
-        self.assertFalse('TransferSyntaxUID' in ds.file_meta)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
+        assert 'TransferSyntaxUID' not in ds.file_meta
 
     def test_transfer_syntax_raises(self):
-        """Test TransferSyntaxUID is raises NotImplementedError if ImplVRBE."""
+        """Test TransferSyntaxUID is raises
+           NotImplementedError if ImplVRBE."""
         ds = read_file(rtplan_name)
         ds.is_implicit_VR = True
         ds.is_little_endian = False
+
         with pytest.raises(NotImplementedError):
-            ds.save_as(self.fp, write_like_original=False)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
+
+    def test_media_storage_sop_class_uid_added(self):
+        """Test MediaStorageSOPClassUID and InstanceUID are added."""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = True
+        ds.SOPClassUID = CTImageStorage
+        ds.SOPInstanceUID = '1.2.3'
+        ds.save_as(fp, write_like_original=False)
+        assert ds.file_meta.MediaStorageSOPClassUID == CTImageStorage
+        assert ds.file_meta.MediaStorageSOPInstanceUID == '1.2.3'
+
+    def test_write_no_file_meta(self):
+        """Test writing a dataset with no file_meta"""
+        fp = DicomBytesIO()
+        version = 'PYDICOM ' + __version__
+        ds = read_file(rtplan_name)
+        transfer_syntax = ds.file_meta.TransferSyntaxUID
+        ds.file_meta = Dataset()
+        ds.save_as(fp, write_like_original=False)
+        fp = BytesIO(fp.getvalue())  # Workaround to avoid #358
+        out = read_file(fp)
+        assert out.file_meta.MediaStorageSOPClassUID == ds.SOPClassUID
+        assert out.file_meta.MediaStorageSOPInstanceUID == ds.SOPInstanceUID
+        assert (
+            out.file_meta.ImplementationClassUID == PYDICOM_IMPLEMENTATION_UID)
+        assert (out.file_meta.ImplementationVersionName == version)
+        assert out.file_meta.TransferSyntaxUID == transfer_syntax
+
+        fp = DicomBytesIO()
+        del ds.file_meta
+        ds.save_as(fp, write_like_original=False)
+        fp = BytesIO(fp.getvalue())  # Workaround to avoid #358
+        out = read_file(fp)
+        assert (out.file_meta.MediaStorageSOPClassUID == ds.SOPClassUID)
+        assert (
+            out.file_meta.MediaStorageSOPInstanceUID == ds.SOPInstanceUID)
+        assert (
+            out.file_meta.ImplementationClassUID == PYDICOM_IMPLEMENTATION_UID)
+        assert (out.file_meta.ImplementationVersionName == version)
+        assert out.file_meta.TransferSyntaxUID == transfer_syntax
 
     def test_raise_no_file_meta(self):
         """Test exception is raised if trying to write with no file_meta."""
         ds = read_file(rtplan_name)
+        del ds.SOPInstanceUID
         ds.file_meta = Dataset()
-
         with pytest.raises(ValueError):
-            ds.save_as(self.fp, write_like_original=False)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
         del ds.file_meta
         with pytest.raises(ValueError):
-            ds.save_as(self.fp, write_like_original=False)
+            ds.save_as(DicomBytesIO(), write_like_original=False)
+
+    def test_add_file_meta(self):
+        """Test that file_meta is added if it doesn't exist"""
+        fp = DicomBytesIO()
+        ds = Dataset()
+        ds.is_little_endian = True
+        ds.is_implicit_VR = True
+        ds.SOPClassUID = CTImageStorage
+        ds.SOPInstanceUID = '1.2.3'
+        ds.save_as(fp, write_like_original=False)
+        assert isinstance(ds.file_meta, Dataset)
 
     def test_standard(self):
         """Test preamble + file_meta + dataset written OK."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         preamble = ds.preamble[:]
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        self.assertEqual(self.fp.read(128), preamble)
-        self.assertEqual(self.fp.read(4), b'DICM')
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == preamble
+        assert fp.read(4) == b'DICM'
 
-        fp = BytesIO(self.fp.getvalue())  # Workaround to avoid #358
+        fp = BytesIO(fp.getvalue())  # Workaround to avoid #358
         ds_out = read_file(fp)
-        self.assertEqual(ds_out.preamble, preamble)
-        self.assertTrue('PatientID' in ds_out)
-        self.assertTrue('TransferSyntaxUID' in ds_out.file_meta)
+        assert ds_out.preamble == preamble
+        assert 'PatientID' in ds_out
+        assert 'TransferSyntaxUID' in ds_out.file_meta
 
     def test_commandset_no_written(self):
-        """Test that Command Set elements aren't written"""
+        """Test that Command Set elements aren't written."""
+        fp = DicomBytesIO()
         ds = read_file(ct_name)
         preamble = ds.preamble[:]
         ds.MessageID = 3
-        ds.save_as(self.fp, write_like_original=False)
-        self.fp.seek(0)
-        self.assertEqual(self.fp.read(128), preamble)
-        self.assertEqual(self.fp.read(4), b'DICM')
-        self.assertTrue('MessageID' in ds)
+        ds.save_as(fp, write_like_original=False)
+        fp.seek(0)
+        assert fp.read(128) == preamble
+        assert fp.read(4) == b'DICM'
+        assert 'MessageID' in ds
 
-        fp = BytesIO(self.fp.getvalue())  # Workaround to avoid #358
+        fp = BytesIO(fp.getvalue())  # Workaround to avoid #358
         ds_out = read_file(fp)
-        self.assertEqual(ds_out.preamble, preamble)
-        self.assertTrue('PatientID' in ds_out)
-        self.assertTrue('TransferSyntaxUID' in ds_out.file_meta)
-        self.assertFalse('MessageID' in ds_out)
+        assert ds_out.preamble == preamble
+        assert 'PatientID' in ds_out
+        assert 'TransferSyntaxUID' in ds_out.file_meta
+        assert 'MessageID' not in ds_out
 
 
-class TestWriteFileMetaInfoToStandard(unittest.TestCase):
+class TestWriteFileMetaInfoToStandard(object):
     """Unit tests for writing File Meta Info to the DICOM standard."""
-    def setUp(self):
-        """Create an empty file-like for use in testing."""
-        self.fp = DicomBytesIO()
-
     def test_bad_elements(self):
         """Test that non-group 2 elements aren't written to the file meta."""
+        fp = DicomBytesIO()
         meta = Dataset()
         meta.PatientID = '12345678'
         meta.MediaStorageSOPClassUID = '1.1'
         meta.MediaStorageSOPInstanceUID = '1.2'
         meta.TransferSyntaxUID = '1.3'
         meta.ImplementationClassUID = '1.4'
-        self.assertRaises(ValueError, write_file_meta_info, self.fp, meta,
-                          enforce_standard=True)
+        with pytest.raises(ValueError):
+            write_file_meta_info(fp, meta, enforce_standard=True)
 
     def test_missing_elements(self):
         """Test that missing required elements raises ValueError."""
+        fp = DicomBytesIO()
         meta = Dataset()
-        self.assertRaises(ValueError, write_file_meta_info, self.fp, meta)
+        with pytest.raises(ValueError):
+            write_file_meta_info(fp, meta)
         meta.MediaStorageSOPClassUID = '1.1'
-        self.assertRaises(ValueError, write_file_meta_info, self.fp, meta)
+        with pytest.raises(ValueError):
+            write_file_meta_info(fp, meta)
         meta.MediaStorageSOPInstanceUID = '1.2'
-        self.assertRaises(ValueError, write_file_meta_info, self.fp, meta)
+        with pytest.raises(ValueError):
+            write_file_meta_info(fp, meta)
         meta.TransferSyntaxUID = '1.3'
-        self.assertRaises(ValueError, write_file_meta_info, self.fp, meta)
-        meta.ImplementationClassUID = '1.4'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
+        write_file_meta_info(fp, meta, enforce_standard=True)
 
     def test_group_length(self):
         """Test that the value for FileMetaInformationGroupLength is OK."""
+        fp = DicomBytesIO()
         meta = Dataset()
         meta.MediaStorageSOPClassUID = '1.1'
         meta.MediaStorageSOPInstanceUID = '1.2'
         meta.TransferSyntaxUID = '1.3'
-        meta.ImplementationClassUID = '1.4'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
+        write_file_meta_info(fp, meta, enforce_standard=True)
 
-        # 74 in total, - 12 for group length = 62
-        self.fp.seek(8)
-        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')
+        class_length = len(PYDICOM_IMPLEMENTATION_UID)
+        if class_length % 2:
+            class_length += 1
+        version_length = len(meta.ImplementationVersionName)
+        # Padded to even length
+        if version_length % 2:
+            version_length += 1
+
+        fp.seek(8)
+        test_length = unpack('<I', fp.read(4))[0]
+        assert test_length == 66 + class_length + version_length
 
     def test_group_length_updated(self):
         """Test that FileMetaInformationGroupLength gets updated if present."""
+        fp = DicomBytesIO()
         meta = Dataset()
         meta.FileMetaInformationGroupLength = 100  # Not actual length
         meta.MediaStorageSOPClassUID = '1.1'
         meta.MediaStorageSOPInstanceUID = '1.2'
         meta.TransferSyntaxUID = '1.3'
-        meta.ImplementationClassUID = '1.4'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
-
-        self.fp.seek(8)
-        self.assertEqual(self.fp.read(4), b'\x3E\x00\x00\x00')
+        write_file_meta_info(fp, meta, enforce_standard=True)
+
+        class_length = len(PYDICOM_IMPLEMENTATION_UID)
+        if class_length % 2:
+            class_length += 1
+        version_length = len(meta.ImplementationVersionName)
+        # Padded to even length
+        if version_length % 2:
+            version_length += 1
+
+        fp.seek(8)
+        test_length = unpack('<I', fp.read(4))[0]
+        assert test_length == 66 + class_length + version_length
         # Check original file meta is unchanged/updated
-        self.assertEqual(meta.FileMetaInformationGroupLength, 62)
-        self.assertEqual(meta.FileMetaInformationVersion, b'\x00\x01')
-        self.assertEqual(meta.MediaStorageSOPClassUID, '1.1')
-        self.assertEqual(meta.MediaStorageSOPInstanceUID, '1.2')
-        self.assertEqual(meta.TransferSyntaxUID, '1.3')
-        self.assertEqual(meta.ImplementationClassUID, '1.4')
+        assert meta.FileMetaInformationGroupLength == 110
+        assert meta.FileMetaInformationVersion == b'\x00\x01'
+        assert meta.MediaStorageSOPClassUID == '1.1'
+        assert meta.MediaStorageSOPInstanceUID == '1.2'
+        assert meta.TransferSyntaxUID == '1.3'
+        # Updated to meet standard
+        assert meta.ImplementationClassUID == PYDICOM_IMPLEMENTATION_UID
+        assert meta.ImplementationVersionName == 'PYDICOM ' + __version__
 
     def test_version(self):
         """Test that the value for FileMetaInformationVersion is OK."""
+        fp = DicomBytesIO()
         meta = Dataset()
         meta.MediaStorageSOPClassUID = '1.1'
         meta.MediaStorageSOPInstanceUID = '1.2'
         meta.TransferSyntaxUID = '1.3'
-        meta.ImplementationClassUID = '1.4'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
+        write_file_meta_info(fp, meta, enforce_standard=True)
 
-        self.fp.seek(12 + 12)
-        self.assertEqual(self.fp.read(2), b'\x00\x01')
+        fp.seek(12 + 12)
+        assert fp.read(2) == b'\x00\x01'
+
+    def test_implementation_version_name_length(self):
+        """Test that the written Implementation Version Name length is OK"""
+        fp = DicomBytesIO()
+        meta = Dataset()
+        meta.MediaStorageSOPClassUID = '1.1'
+        meta.MediaStorageSOPInstanceUID = '1.2'
+        meta.TransferSyntaxUID = '1.3'
+        write_file_meta_info(fp, meta, enforce_standard=True)
+        version_length = len(meta.ImplementationVersionName)
+        # VR of SH, 16 bytes max
+        assert version_length <= 16
+
+    def test_implementation_class_uid_length(self):
+        """Test that the written Implementation Class UID length is OK"""
+        fp = DicomBytesIO()
+        meta = Dataset()
+        meta.MediaStorageSOPClassUID = '1.1'
+        meta.MediaStorageSOPInstanceUID = '1.2'
+        meta.TransferSyntaxUID = '1.3'
+        write_file_meta_info(fp, meta, enforce_standard=True)
+        class_length = len(meta.ImplementationClassUID)
+        # VR of UI, 64 bytes max
+        assert class_length <= 64
 
     def test_filelike_position(self):
         """Test that the file-like's ending position is OK."""
-        # 8 + 4 bytes FileMetaInformationGroupLength
-        # 12 + 2 bytes FileMetaInformationVersion
-        # 8 + 4 bytes MediaStorageSOPClassUID
-        # 8 + 4 bytes MediaStorageSOPInstanceUID
-        # 8 + 4 bytes TransferSyntaxUID
-        # 8 + 4 bytes ImplementationClassUID
-        # 74 bytes total
+        fp = DicomBytesIO()
         meta = Dataset()
         meta.MediaStorageSOPClassUID = '1.1'
         meta.MediaStorageSOPInstanceUID = '1.2'
         meta.TransferSyntaxUID = '1.3'
-        meta.ImplementationClassUID = '1.4'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
-        self.assertEqual(self.fp.tell(), 74)
+        write_file_meta_info(fp, meta, enforce_standard=True)
 
-        # 8 + 6 bytes ImplementationClassUID
-        # 76 bytes total, group length 64
-        self.fp.seek(0)
-        meta.ImplementationClassUID = '1.4.1'
-        write_file_meta_info(self.fp, meta, enforce_standard=True)
+        # 8 + 4 bytes FileMetaInformationGroupLength
+        # 12 + 2 bytes FileMetaInformationVersion
+        # 8 + 4 bytes MediaStorageSOPClassUID
+        # 8 + 4 bytes MediaStorageSOPInstanceUID
+        # 8 + 4 bytes TransferSyntaxUID
+        # 8 + XX bytes ImplementationClassUID
+        # 8 + YY bytes ImplementationVersionName
+        # 78 + XX + YY bytes total
+        class_length = len(PYDICOM_IMPLEMENTATION_UID)
+        if class_length % 2:
+            class_length += 1
+        version_length = len(meta.ImplementationVersionName)
+        # Padded to even length
+        if version_length % 2:
+            version_length += 1
+
+        assert fp.tell() == 78 + class_length + version_length
+
+        fp = DicomBytesIO()
+        # 8 + 6 bytes MediaStorageSOPInstanceUID
+        meta.MediaStorageSOPInstanceUID = '1.4.1'
+        write_file_meta_info(fp, meta, enforce_standard=True)
         # Check File Meta length
-        self.assertEqual(self.fp.tell(), 76)
-        # Check Group Length
-        self.fp.seek(8)
-        self.assertEqual(self.fp.read(4), b'\x40\x00\x00\x00')
+        assert fp.tell() == 80 + class_length + version_length
+
+        # Check Group Length - 68 + XX + YY as bytes
+        fp.seek(8)
+        test_length = unpack('<I', fp.read(4))[0]
+        assert test_length == 68 + class_length + version_length
 
 
 class TestWriteNonStandard(unittest.TestCase):
@@ -1288,9 +1491,11 @@ class TestWriteNonStandard(unittest.TestCase):
         ds.Status = 0x0000
         ds.save_as(self.fp, write_like_original=True)
         self.fp.seek(0)
-        self.assertNotEqual(self.fp.read(128), preamble)
+        self.assertNotEqual(self.fp.read(128),
+                            preamble)
         self.fp.seek(0)
-        self.assertNotEqual(self.fp.read(128), b'\x00' * 128)
+        self.assertNotEqual(self.fp.read(128),
+                            b'\x00' * 128)
         self.fp.seek(0)
         self.assertNotEqual(self.fp.read(4), b'DICM')
         # Ensure Command Set Elements written as little endian implicit VR
@@ -1314,7 +1519,7 @@ class TestWriteNonStandard(unittest.TestCase):
         ds.Status = 0x0000
         ds.save_as(self.fp, write_like_original=True)
         self.fp.seek(0)
-        self.assertRaises(EOFError, self.fp.read, 128)
+        self.assertRaises(EOFError, self.fp.read, 128, need_exact_length=True)
         self.fp.seek(0)
         self.assertNotEqual(self.fp.read(4), b'DICM')
         # Ensure Command Set Elements written as little endian implicit VR
diff --git a/pydicom/tests/test_gdcm_pixel_data.py b/pydicom/tests/test_gdcm_pixel_data.py
index a55afaa33..1d0844135 100644
--- a/pydicom/tests/test_gdcm_pixel_data.py
+++ b/pydicom/tests/test_gdcm_pixel_data.py
@@ -5,6 +5,7 @@ import pytest
 import pydicom
 import logging
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 from pydicom.tag import Tag
 gdcm_missing_message = "GDCM is not available in this test environment"
 gdcm_present_message = "GDCM is being tested"
@@ -18,8 +19,7 @@ except ImportError as e:
 
 test_gdcm_decoder = have_gdcm_handler
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 empty_number_tags_name = os.path.join(
     test_files, "reportsi_with_empty_number_tags.dcm")
diff --git a/pydicom/tests/test_getdata.py b/pydicom/tests/test_getdata.py
new file mode 100644
index 000000000..59e0a78b1
--- /dev/null
+++ b/pydicom/tests/test_getdata.py
@@ -0,0 +1,41 @@
+"""Test the data manager"""
+
+import os
+import unittest
+from os.path import basename
+from pydicom.data import (get_charset_files,
+                          get_testdata_files)
+
+from pydicom.data.base import DATA_ROOT
+
+
+class TestGetData(unittest.TestCase):
+
+    def test_get_dataset(self):
+        """Test the different functions
+        to get lists of data files"""
+
+        # Test base locations
+        charbase = os.path.join(DATA_ROOT, 'charset_files')
+        self.assertTrue(os.path.exists(charbase))
+
+        testbase = os.path.join(DATA_ROOT, 'test_files')
+        self.assertTrue(os.path.exists(testbase))
+
+        # Test file get
+        chardata = get_charset_files()
+        self.assertTrue(len(chardata) > 15)
+
+        # Test that top level file is included
+        bases = [basename(x) for x in chardata]
+        self.assertTrue('charlist.py' in bases)
+
+        # Test that subdirectory files included
+        testdata = get_testdata_files()
+        bases = [basename(x) for x in testdata]
+        self.assertTrue('2693' in bases)
+        self.assertTrue(len(testdata) > 70)
+
+        # The files should be from their respective bases
+        [self.assertTrue(testbase in x) for x in testdata]
+        [self.assertTrue(charbase in x) for x in chardata]
diff --git a/pydicom/tests/test_jpeg_ls_pixel_data.py b/pydicom/tests/test_jpeg_ls_pixel_data.py
index b3054a6b7..b5f2a07c3 100644
--- a/pydicom/tests/test_jpeg_ls_pixel_data.py
+++ b/pydicom/tests/test_jpeg_ls_pixel_data.py
@@ -4,6 +4,7 @@ import sys
 import pytest
 import pydicom
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 jpeg_ls_missing_message = ("jpeg_ls is not available "
                            "in this test environment")
 jpeg_ls_present_message = "jpeg_ls is being tested"
@@ -22,8 +23,7 @@ except ImportError:
 
 test_jpeg_ls_decoder = have_numpy_handler and have_jpeg_ls_handler
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 empty_number_tags_name = os.path.join(
     test_files, "reportsi_with_empty_number_tags.dcm")
diff --git a/pydicom/tests/test_misc.py b/pydicom/tests/test_misc.py
index 040938495..d42f7f4c5 100644
--- a/pydicom/tests/test_misc.py
+++ b/pydicom/tests/test_misc.py
@@ -3,10 +3,11 @@
 import unittest
 import os.path as osp
 
+from pydicom.data import DATA_ROOT
 from pydicom.misc import is_dicom, size_in_bytes
 
-test_file = osp.join(osp.dirname(osp.abspath(__file__)), 'test_files',
-                     'CT_small.dcm')
+test_files = osp.join(DATA_ROOT, 'test_files')
+test_file = osp.join(test_files, 'CT_small.dcm')
 
 
 class TestMisc(unittest.TestCase):
diff --git a/pydicom/tests/test_multival.py b/pydicom/tests/test_multival.py
index b44ad7f65..df277e640 100644
--- a/pydicom/tests/test_multival.py
+++ b/pydicom/tests/test_multival.py
@@ -26,6 +26,18 @@ class MultiValuetests(unittest.TestCase):
             self.assertTrue(isinstance(val, (DSfloat, DSdecimal)),
                             "Multi-value DS item not converted to DS")
 
+    def testEmptyElements(self):
+        """MultiValue: Empty number string elements are not converted..."""
+        multival = MultiValue(DSfloat, ['1.0', ''])
+        self.assertEqual(1.0, multival[0])
+        self.assertEqual('', multival[1])
+        multival = MultiValue(IS, ['1', ''])
+        self.assertEqual(1, multival[0])
+        self.assertEqual('', multival[1])
+        multival = MultiValue(DSdecimal, ['1', ''])
+        self.assertEqual(1, multival[0])
+        self.assertEqual('', multival[1])
+
     def testLimits(self):
         """MultiValue: Raise error if any item outside DICOM limits...."""
         original_flag = config.enforce_valid_values
@@ -52,6 +64,14 @@ class MultiValuetests(unittest.TestCase):
         self.assertEqual(multival[1], 7,
                          "Item set by index is not correct value")
 
+    def testDeleteIndex(self):
+        """MultiValue: Deleting item at index behaves as expected..."""
+        multival = MultiValue(IS, [1, 5, 10])
+        del multival[1]
+        self.assertEqual(2, len(multival))
+        self.assertEqual(multival[0], 1)
+        self.assertEqual(multival[1], 10)
+
     def testExtend(self):
         """MultiValue: Extending a list converts all to required type"""
         multival = MultiValue(IS, [1, 5, 10])
diff --git a/pydicom/tests/test_numpy_pixel_data.py b/pydicom/tests/test_numpy_pixel_data.py
index 1f6a244e0..6c078c041 100644
--- a/pydicom/tests/test_numpy_pixel_data.py
+++ b/pydicom/tests/test_numpy_pixel_data.py
@@ -4,6 +4,7 @@ import sys
 import pytest
 import pydicom
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 from pydicom.tag import Tag
 numpy_missing_message = ("numpy is not available "
                          "in this test environment")
@@ -15,8 +16,7 @@ try:
 except ImportError:
     have_numpy_handler = False
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 empty_number_tags_name = os.path.join(
     test_files, "reportsi_with_empty_number_tags.dcm")
diff --git a/pydicom/tests/test_pillow_pixel_data.py b/pydicom/tests/test_pillow_pixel_data.py
index d146ff169..3999e8d2e 100644
--- a/pydicom/tests/test_pillow_pixel_data.py
+++ b/pydicom/tests/test_pillow_pixel_data.py
@@ -4,6 +4,7 @@ import sys
 import pytest
 import pydicom
 from pydicom.filereader import read_file
+from pydicom.data import DATA_ROOT
 from pydicom.tag import Tag
 pillow_missing_message = ("pillow is not available "
                           "in this test environment")
@@ -32,9 +33,7 @@ test_pillow_jpeg_decoder = (test_pillow_decoder and
 test_pillow_jpeg2000_decoder = (test_pillow_decoder and
                                 have_pillow_jpeg2000_plugin)
 
-
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 
 empty_number_tags_name = os.path.join(
     test_files, "reportsi_with_empty_number_tags.dcm")
diff --git a/pydicom/tests/test_valuerep.py b/pydicom/tests/test_valuerep.py
index f20f3d614..e7eaade57 100644
--- a/pydicom/tests/test_valuerep.py
+++ b/pydicom/tests/test_valuerep.py
@@ -22,6 +22,7 @@ import platform
 from pydicom.compat import in_py2
 from pydicom import config
 from pydicom import valuerep
+from pydicom.data import DATA_ROOT
 import unittest
 
 have_dateutil = True
@@ -52,8 +53,7 @@ try:
 except ImportError:
     import pickle
 
-test_dir = os.path.dirname(__file__)
-test_files = os.path.join(test_dir, 'test_files')
+test_files = os.path.join(DATA_ROOT, 'test_files')
 badvr_name = os.path.join(test_files, "badVR.dcm")
 default_encoding = 'iso8859'