git @ Cat's Eye Technologies Falderal / 87523db
Refactor, rename two more tests. Chris Pressey 5 years ago
11 changed file(s) with 204 addition(s) and 206 deletion(s). Raw diff Collapse all Expand all
5454 for filename in args:
5555 documents.append(Document.load(filename))
5656 for document in documents:
57 tests += document.parse_lines_to_tests(functionalities)
57 tests += document.extract_tests(functionalities)
5858
5959 if not options.cavalier:
6060 if not documents:
314314 if pattern_prefixes == [u'->']:
315315 return Pragma(line_num=self.line_num, filename=self.filename, lines=pattern[0][1])
316316 elif pattern_prefixes[-1] in [u'= ', u'? ']:
317 # TODO: several things
318
319317 if state.current_functionality is None:
320318 raise FalderalSyntaxError(
321319 ("line %d: " % self.line_num) +
325323 input_block = make_block_from_pattern(TestInput, pattern, u'+ ') or state.last_test_input_block
326324
327325 if pattern_prefixes[-1] == u'= ':
328 expectation_block = make_block_from_pattern(ExpectedResult, pattern, u'= ')
326 expectation_block = make_block_from_pattern(Block, pattern, u'= ')
329327 expectation = OutputOutcome(expectation_block.text())
330328 elif pattern_prefixes[-1] == u'? ':
331 expectation_block = make_block_from_pattern(ExpectedError, pattern, u'? ')
329 expectation_block = make_block_from_pattern(Block, pattern, u'? ')
332330 expectation = ErrorOutcome(expectation_block.text())
333331 else:
334332 raise NotImplementedError
379377 pass
380378
381379
382 class ExpectedError(Block):
383 pass
384
385
386 class ExpectedResult(Block):
387 pass
388
389
390380 class InterveningText(Block):
391381 pass
392382
429419 line = line.rstrip(u'\r\n')
430420 self.lines.append(line)
431421
432 def parse_lines_to_tests(self, functionalities):
433 r"""Parse the lines of the Document into Tests.
434
435 | >>> d = Document()
436 | >>> d.append(u'This is a test file.')
437 | >>> d.append(u' -> This is a pragma.')
438 | >>> d.append(u'')
439 | >>> d.append(u" | This is some test input.\n")
440 | >>> d.append(u" | It extends over two lines.")
441 | >>> d.append(u' ? Expected Error')
442 | >>> d.append(u'')
443 | >>> d.append(u' | Test with input')
444 | >>> d.append(u' + input-for-test')
445 | >>> d.append(u' = Expected result on output')
446 | >>> d.parse_lines_to_blocks()
447 | >>> [block.lines for block in d.blocks if isinstance(block, InterveningText)]
448 | [[u'This is a test file.']]
449 | >>> [b.__class__.__name__ for b in d.blocks]
450 | ['InterveningText', 'Pragma', 'TestBody', 'ExpectedError',
451 | 'TestBody', 'TestInput', 'ExpectedResult']
452 | >>> [b.line_num for b in d.blocks]
453 | [1, 2, 4, 4, 8, 8, 8]
422 def parse_lines_to_blocks(self):
423 r"""Parse the lines of the Document into Blocks.
424
425 >>> d = Document()
426 >>> d.append(u'This is a test file.')
427 >>> d.append(u' -> This is a pragma.')
428 >>> d.append(u'')
429 >>> d.append(u" | This is some test input.\n")
430 >>> d.append(u" | It extends over two lines.")
431 >>> d.append(u' ? Expected Error')
432 >>> d.append(u'')
433 >>> d.append(u' | Test with input')
434 >>> d.append(u' + input-for-test')
435 >>> d.append(u' = Expected result on output')
436 >>> blocks = d.parse_lines_to_blocks()
437 >>> [block.lines for block in blocks if isinstance(block, InterveningText)]
438 [[u'This is a test file.'], [u''], [u'']]
439 >>> [b.__class__.__name__ for b in blocks]
440 ['InterveningText', 'Block', 'InterveningText', 'Block', 'InterveningText', 'Block']
441 >>> [b.line_num for b in blocks]
442 [1, 2, 3, 4, 7, 8]
443
444 """
445 indent = None
446 blocks = []
447 line_num = 1
448 block = None
449
450 for line in self.lines:
451 # make sure we get a Block to start with
452 if indent is None:
453 if line.startswith(u' '):
454 indent = u''
455 else:
456 indent = u' '
457
458 if indent == u'':
459 if line.startswith(u' '):
460 indent = u' '
461 if block is not None:
462 blocks.append(block)
463 block = Block(
464 line_num=line_num,
465 filename=self.filename
466 )
467 elif indent == u' ':
468 if not line.startswith(u' '):
469 indent = u''
470 if block is not None:
471 blocks.append(block)
472 block = InterveningText(
473 line_num=line_num,
474 filename=self.filename
475 )
476
477 line = line[len(indent):]
478
479 block.append(line)
480 line_num += 1
481
482 if block is not None:
483 blocks.append(block)
484
485 return blocks
486
487 def parse_blocks_to_tests(self, blocks, functionalities):
488 state = ParseState()
489 state.functionalities = functionalities
490
491 tests = []
492 for block in blocks:
493 if isinstance(block, InterveningText):
494 if block.is_empty():
495 continue
496 state.last_desc_block = block
497 continue
498
499 test_or_pragma = block.classify(state)
500
501 if test_or_pragma is None:
502 # It was just some indented text which doesn't concern us
503 pass
504 elif isinstance(test_or_pragma, Test):
505 tests.append(test_or_pragma)
506 elif isinstance(test_or_pragma, Pragma):
507 test_or_pragma.execute(state)
508 else:
509 raise NotImplementedError('need Pragma or Test, not ' + repr(test_or_pragma))
510
511 return tests
512
513 def extract_tests(self, functionalities):
514 r"""Extract all Tests from this Document.
454515
455516 >>> functionalities = {}
456517 >>> d = Document()
457518 >>> d.append(u"This is a text file.")
458519 >>> d.append(u'It contains NO tests.')
459 >>> d.parse_lines_to_tests(functionalities)
520 >>> d.extract_tests(functionalities)
460521 []
461522
462523 >>> d = Document()
465526 >>> d.append(u'')
466527 >>> d.append(u" | This is some test body.")
467528 >>> d.append(u' = Expected result')
468 >>> d.parse_lines_to_tests(functionalities)
529 >>> d.extract_tests(functionalities)
469530 [Test(body_block=TestBody(line_num=4), input_block=None,
470531 expectation=OutputOutcome(u'Expected result'),
471532 functionality=Functionality(u'Parse Thing'),
491552 >>> d.append(u'')
492553 >>> d.append(u" | Thing")
493554 >>> d.append(u' ? Oops')
494 >>> tests = d.parse_lines_to_tests(functionalities)
555 >>> tests = d.extract_tests(functionalities)
495556 >>> [t.body for t in tests]
496557 [u'This is some test body.\nIt extends over two lines.',
497558 u'Test with input', u'Test with input', u'Thing']
514575 >>> d = Document()
515576 >>> d.append(u" | This is some test body.")
516577 >>> d.append(u' = Expected')
517 >>> d.parse_lines_to_tests({})
578 >>> d.extract_tests({})
518579 Traceback (most recent call last):
519580 ...
520581 FalderalSyntaxError: line 1: functionality under test not specified
522583 >>> d = Document()
523584 >>> d.append(u'This is a test file.')
524585 >>> d.append(u' ? Expected Error')
525 >>> d.parse_lines_to_tests({})
586 >>> d.extract_tests({})
526587 Traceback (most recent call last):
527588 ...
528589 FalderalSyntaxError: line 2: expectation must be preceded by test body or test input
530591 >>> d = Document()
531592 >>> d.append(u' -> Hello, this is pragma')
532593 >>> d.append(u' = Expected')
533 >>> d.parse_lines_to_tests({})
594 >>> d.extract_tests({})
534595 Traceback (most recent call last):
535596 ...
536597 FalderalSyntaxError: line 1: incorrectly formatted test block
538599 >>> d = Document()
539600 >>> d.append(u' | This is test')
540601 >>> d.append(u'This is text')
541 >>> d.parse_lines_to_tests({})
602 >>> d.extract_tests({})
542603 Traceback (most recent call last):
543604 ...
544605 FalderalSyntaxError: line 1: test body must be followed by expectation or test input
546607 >>> d = Document()
547608 >>> d.append(u' -> Hello, this is pragma')
548609 >>> d.append(u' + Input to where exactly?')
549 >>> d.parse_lines_to_tests({})
610 >>> d.extract_tests({})
550611 Traceback (most recent call last):
551612 ...
552613 FalderalSyntaxError: line 1: incorrectly formatted test block
558619 >>> d.append(u'')
559620 >>> d.append(u' -> Functionality "Parse Stuff" is')
560621 >>> d.append(u' -> implemented by shell command "pxxxy"')
561 >>> tests = d.parse_lines_to_tests(funs)
622 >>> tests = d.extract_tests(funs)
562623 >>> len(funs.keys())
563624 1
564625 >>> [i for i in funs["Parse Stuff"].implementations]
565626 [ShellImplementation(u'parse'), ShellImplementation(u'pxxxy')]
566627
567628 """
568 indent = None
569 blocks = []
570 line_num = 1
571 block = None
572
573 for line in self.lines:
574 # make sure we get a Block to start with
575 if indent is None:
576 if line.startswith(u' '):
577 indent = u''
578 else:
579 indent = u' '
580
581 if indent == u'':
582 if line.startswith(u' '):
583 indent = u' '
584 if block is not None:
585 blocks.append(block)
586 block = Block(
587 line_num=line_num,
588 filename=self.filename
589 )
590 elif indent == u' ':
591 if not line.startswith(u' '):
592 indent = u''
593 if block is not None:
594 blocks.append(block)
595 block = InterveningText(
596 line_num=line_num,
597 filename=self.filename
598 )
599
600 line = line[len(indent):]
601
602 block.append(line)
603 line_num += 1
604
605 if block is not None:
606 blocks.append(block)
607
608 # now process Blocks into Tests
609
610 state = ParseState()
611 state.functionalities = functionalities
612
613 tests = []
614 for block in blocks:
615 if isinstance(block, InterveningText):
616 if block.is_empty():
617 continue
618 state.last_desc_block = block
619 continue
620
621 test_or_pragma = block.classify(state)
622
623 if test_or_pragma is None:
624 # It was just some indented text which doesn't concern us
625 pass
626 elif isinstance(test_or_pragma, Test):
627 tests.append(test_or_pragma)
628 elif isinstance(test_or_pragma, Pragma):
629 test_or_pragma.execute(state)
630 else:
631 raise NotImplementedError('need Pragma or Test, not ' + repr(test_or_pragma))
632
629 blocks = self.parse_lines_to_blocks()
630 tests = self.parse_blocks_to_tests(blocks, functionalities)
633631 return tests
634632
635633
66 cd tests
77
88 FIRST_TESTS="
9 test-pass-fail test-no-functionality test-ill-formed
10 test4 test5
9 test-pass-fail test-no-functionality test-ill-formed test-no-test-body
10 test-var-subst-no-eol
1111 test-utf8 test-crlf
1212 test-bad-indentation
1313 test-input-sections test-shared-body
0 FalderalSyntaxError: line 13: expectation must be preceded by test body or test input
0 Falderal Test 4
1 ---------------
2
3 Another Falderal document which is ill-formed.
4
5 -> Functionality "Cat" is implemented by
6 -> shell command "python cat.py"
7
8 -> Tests for functionality "Cat"
9
10 Cat cats.
11
12 = meow
13
14 Oops, I didn't include a test body.
0 --------------------------------
1 Total test runs: 10, failures: 0
2 --------------------------------
0 Falderal Test 5
1 ---------------
2
3 Tests for variable substitution, and missing EOL at end
4 of output.
5
6 Note the use of single quotes around the `%(test-body-text)` variable;
7 without these, shell chaos is likely to result.
8
9 -> Functionality "Echo" is implemented by
10 -> shell command "python echo.py '%(test-body-text)'"
11
12 -> Tests for functionality "Echo"
13
14 | hello
15 = hello
16
17 | hi
18 | hi
19 = hi
20 = hi
21
22 -> Functionality "Echo, no newline" is implemented by
23 -> shell command "python echo.py -n '%(test-body-text)'"
24
25 -> Tests for functionality "Echo, no newline"
26
27 | hello
28 = hello
29
30 | hi
31 | hi
32 = hi
33 = hi
34
35 Note that single quotes needn't be supplied around `%(test-body-file)`
36 or `%(output-file)`.
37
38 -> Functionality "Cat, from file" is implemented by
39 -> shell command "python cat.py -f %(test-body-file)"
40
41 -> Tests for functionality "Cat, from file"
42
43 | hello
44 = hello
45
46 | hi
47 | hi
48 = hi
49 = hi
50
51 -> Functionality "Cat, to file" is implemented by
52 -> shell command "python cat.py -o %(output-file)"
53
54 -> Tests for functionality "Cat, to file"
55
56 | hello
57 = hello
58
59 | hi
60 | hi
61 = hi
62 = hi
63
64 -> Functionality "Cat, to and from file" is implemented by
65 -> shell command "python cat.py -f %(test-body-file) -o %(output-file)"
66
67 -> Tests for functionality "Cat, to and from file"
68
69 | hello
70 = hello
71
72 | hi
73 | hi
74 = hi
75 = hi
+0
-1
tests/test4.expected less more
0 FalderalSyntaxError: line 13: expectation must be preceded by test body or test input
+0
-15
tests/test4.markdown less more
0 Falderal Test 4
1 ---------------
2
3 Another Falderal document which is ill-formed.
4
5 -> Functionality "Cat" is implemented by
6 -> shell command "python cat.py"
7
8 -> Tests for functionality "Cat"
9
10 Cat cats.
11
12 = meow
13
14 Oops, I didn't include a test body.
+0
-3
tests/test5.expected less more
0 --------------------------------
1 Total test runs: 10, failures: 0
2 --------------------------------
+0
-76
tests/test5.markdown less more
0 Falderal Test 5
1 ---------------
2
3 Tests for variable substitution, and missing EOL at end
4 of output.
5
6 Note the use of single quotes around the `%(test-body-text)` variable;
7 without these, shell chaos is likely to result.
8
9 -> Functionality "Echo" is implemented by
10 -> shell command "python echo.py '%(test-body-text)'"
11
12 -> Tests for functionality "Echo"
13
14 | hello
15 = hello
16
17 | hi
18 | hi
19 = hi
20 = hi
21
22 -> Functionality "Echo, no newline" is implemented by
23 -> shell command "python echo.py -n '%(test-body-text)'"
24
25 -> Tests for functionality "Echo, no newline"
26
27 | hello
28 = hello
29
30 | hi
31 | hi
32 = hi
33 = hi
34
35 Note that single quotes needn't be supplied around `%(test-body-file)`
36 or `%(output-file)`.
37
38 -> Functionality "Cat, from file" is implemented by
39 -> shell command "python cat.py -f %(test-body-file)"
40
41 -> Tests for functionality "Cat, from file"
42
43 | hello
44 = hello
45
46 | hi
47 | hi
48 = hi
49 = hi
50
51 -> Functionality "Cat, to file" is implemented by
52 -> shell command "python cat.py -o %(output-file)"
53
54 -> Tests for functionality "Cat, to file"
55
56 | hello
57 = hello
58
59 | hi
60 | hi
61 = hi
62 = hi
63
64 -> Functionality "Cat, to and from file" is implemented by
65 -> shell command "python cat.py -f %(test-body-file) -o %(output-file)"
66
67 -> Tests for functionality "Cat, to and from file"
68
69 | hello
70 = hello
71
72 | hi
73 | hi
74 = hi
75 = hi