JL Peyret
JL Peyret

Reputation: 12204

bash grep - negative match

I want to show flag places in my Python unittests where I have been lazy and de-activated tests.

But I also have conditional executions that are not laziness, they are motivated by performance or system conditions at time of testing. Those are the skipUnless ones and I want to ignore them entirely.

Let's take some inputs that I have put in a file, test_so_bashregex.txt, with some comments.

!ignore this, because skipUnless means I have an acceptable conditional flag
@unittest.skipUnless(do_test, do_test_msg)
def test_conditional_function():
    xxx

!catch these 2, lazy test-passing
@unittest.skip("fb212.test_urls_security_usergroup Test_Detail.test_related fails with 302")
def sometest_function():
    xxx
@unittest.expectedFailure
def test_another_function():
    xxx

!bonus points... ignore things that are commented out
   # @unittest.expectedFailure

Additionally, I can't use a grep -v skipUnless in a pipe because I really want to use egrep -A 3 xxx *.py to give some context, as in:

grep -A 3 "@unittest\." *.py

test_backend_security_meta.py:    @unittest.skip("rewrite - data can be legitimately missing")
test_backend_security_meta.py-    def test_storage(self):
test_backend_security_meta.py-        with getMultiDb() as mdb:
test_backend_security_meta.py-

What I have tried:

Trying @ https://www.debuggex.com/

I tried @unittest\.(.+)(?!(Unless\()) and that didn't work, as it matches the first 3.

Ditto @unittest\.[a-zA-Z]+(?!(Unless\())

@unittest\.skip(?!(Unless\()) worked partially, on the 2 with skip.

All of those do partial matches despite the presence of Unless.

on bash egrep, which is where this going to end up, things don't look much better.

jluc@explore$ egrep '@unittest\..*(?!(Unless))' test_so_bashregex.txt
egrep: repetition-operator operand invalid

Upvotes: 1

Views: 800

Answers (3)

JL Peyret
JL Peyret

Reputation: 12204

OK, I'll put up what I found with sweaver2112's help, but if someone has a good single-stage grep-ready regex, I'll take it.

bash's egrep/grep doesn't like ?! (ref grep: repetition-operator operand invalid). end of story there.

What I have done instead is to pipe it to some extra filters: negative grep -v skipUnless and another one to strip leading comments. These 2 strip out the unwanted lines. But, then pipe their output back into another grep looking for @unittest again and again with the -A 3 flag.

If the negative greps have cleared out a line, it won't show in the last pipestage so drops out of the input. If not, I get my context right back.

egrep -A 3 -n '@unittest\.' test_so_bashregex.txt  | egrep -v "^\s*#" | egrep -v "skipUnless\(" | grep @unittest -A 3

output:

7:@unittest.skip("fb212.test_urls_security_usergroup Test_Detail.test_related fails with 302")
8-def sometest_function():
9-  xxx
10:@unittest.expectedFailure
11-def test_another_function():
12- xxx    

And my actual output from running it on * *.py*, rather than my test.txt file:

 egrep -A 3 -n '@unittest\.' *.py  | egrep -v "\d:\s*#" | egrep -v "skipUnless\(" | grep @unittest -A 3

output:

test_backend_security_meta.py:77:    @unittest.skip("rewrite - data can be legitimately missing")
test_backend_security_meta.py-78-    def test_storage(self):
test_backend_security_meta.py-79-        with getMultiDb() as mdb:
test_backend_security_meta.py-80-
--
test_backend_security_meta.py:98:    @unittest.skip("rewrite - data can be legitimately missing")
test_backend_security_meta.py-99-    def test_get_li_tag_for_object(self):
test_backend_security_meta.py-100-        li = self.mgr.get_li_tag()
test_backend_security_meta.py-101-

Upvotes: 0

tinkertime
tinkertime

Reputation: 3042

How about something like this - grep seems a bit restrictive

items=$(find . -name "*.py")
for item in $items; do
    cat $item | awk ' 
    /^\@unittest.*expectedFailure/{seen_skip=1;}
    /^\@unittest.*skip/{seen_skip=1;}
    /^def/{
        if (seen_skip == 1)
            print "Being lazy at " $1
        seen_skip=0;
    }
    '
done

Upvotes: 1

Scott Weaver
Scott Weaver

Reputation: 7361

you could try this regex:

(?<!#\s)@unittest\.(?!skipUnless)(skip|expectedFailure).*

if you don't care if 'skip' or 'expectedFailure' appear you could simplify it:

(?<!#\s)@unittest\.(?!skipUnless).*

Upvotes: 1

Related Questions