Last active
October 6, 2019 16:49
-
-
Save Ladsgroup/bfb4f4b66384efb8b8d3efea338b6e6b to your computer and use it in GitHub Desktop.
phpunit4 killer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# License: MIT | |
# Run like: "python phpunit4_killer.py /var/lib/mediawiki/extensions/Wikibase/" | |
import os | |
import sys | |
import re | |
import subprocess | |
def find_files(path): | |
files = [] | |
for r, d, f in os.walk(path): | |
for file_name in f: | |
if file_name.endswith('.php'): | |
files.append(os.path.join(r, file_name)) | |
return files | |
def check_file(path): | |
with open(path, 'r', encoding="utf-8") as f: | |
content = f.read() | |
old_content = content | |
cases = re.findall(r'\n\t*?use \\?PHPUnit4And6Compat;', content) | |
literal = '\'(?:[^\'\\\\]|\\\\\')+\'|"(?:[^"\\\\]|\\\\")+"' | |
clname = '(?:[a-zA-Z\\\\]+::class|\$\w+|' + literal + ')' | |
content = re.sub(r'(\$this->)setExpected(Exception\(\s+' + clname + '\s+\);)', r'\1expect\2', content) | |
content = re.sub(r'^(\\t*)(\$this->)setExpectedException\(\s+(' + clname + '),\s+(' + clname + ')\s+\);', r'\1\2expectException( \3 );\n\1\$this->expectExceptionMessage( \4 );', content) | |
content = re.sub(r'(\$this->)get(Mock\(\s+' + clname + '\s+\))', r'\1create\2', content) | |
content = re.sub(r'(\$this->)getMock\(\s+(' + clname + '),\s+\[\],\s+\[\],\s+[\'"]{2},\s+false\s+\)', r'\1createMock( \2 )', content) | |
content = re.sub(r'^(\\t*)(\$this->)getMock\(\s+(' + clname + '),\s+(\[(?:\s*' + literal + ',?)+\])\s+\);', r'\1\2createMock( \3 )\n\1\t->setMethods( \4 )\n\1\t->getMock();', content) | |
if '$this->getMock(' in content or '$this->setExpectedException(' in content: | |
print('Nooooo /o\\') | |
with open(path, 'w', encoding="utf-8") as f: | |
print(path) | |
f.write(content) | |
return | |
for case in cases: | |
content = content.replace(case, '') | |
content = content.replace(', PHPUnit4And6Compat, ', ', ') | |
content = content.replace('use PHPUnit4And6Compat, ', 'use ') | |
content = content.replace(', PHPUnit4And6Compat;', ';') | |
if content == old_content: | |
return | |
with open(path, 'w', encoding="utf-8") as f: | |
print(path) | |
f.write(content) | |
for f in find_files(sys.argv[1]): | |
check_file(f) | |
subprocess.run(["composer", "update"], cwd=sys.argv[1], shell=True) | |
subprocess.run(["composer", "fix"], cwd=sys.argv[1], shell=True) |
Applied your suggestions, regarding removing phpunit trait, I will explain it further in the ticket.
Cool, thanks :) I'm gonna (ab)use it then
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Some other improvements (includes the ones suggested above).
Before line 21, add:
Line21 -->
content = re.sub(r'(\$this->)setExpected(Exception\(\s+' + clname + '\s+\);)', r'\1expect\2', content)
Line22 -->
content = re.sub(r'^(\\t*)(\$this->)setExpectedException\(\s+(' + clname + '),\s+(' + clname + ')\s+\);', r'\1\2expectException( \3 );\n\1\$this->expectExceptionMessage( \4 );', content)
Line23 -->
content = re.sub(r'(\$this->)get(Mock\(\s+' + clname + '\s+\))', r'\1create\2', content)
And after line 23:
These will still leave some edge cases (e.g.: func call, arrays, class members, string concat), but we can fix them manually. We should also replace literal class names with ::class, but I didn't add it because you'd also have to
use
the classes etc.Note: Untested