|
| 1 | +# coding=utf-8 |
| 2 | +""" |
| 3 | +Unit testing of tableformatter with simple cases |
| 4 | +- with a list of tuples as table entries |
| 5 | +- using a list of objects for the table entries |
| 6 | +""" |
| 7 | +import pytest |
| 8 | + |
| 9 | +import tableformatter as tf |
| 10 | + |
| 11 | +# Make the test results reproducible regardless of what color libraries are installed |
| 12 | +tf.TableColors.set_color_library('none') |
| 13 | +tf.set_default_grid(tf.AlternatingRowGrid('', '', '')) |
| 14 | + |
| 15 | + |
| 16 | +class MyRowObject(object): |
| 17 | + """Simple object to demonstrate using a list of objects with TableFormatter""" |
| 18 | + def __init__(self, field1: int, field2: int, field3: int, field4: int): |
| 19 | + self.field1 = field1 |
| 20 | + self.field2 = field2 |
| 21 | + self._field3 = field3 |
| 22 | + self.field4 = field4 |
| 23 | + |
| 24 | + def get_field3(self): |
| 25 | + """Demonstrates accessing object functions""" |
| 26 | + return self._field3 |
| 27 | + |
| 28 | + |
| 29 | +def multiply(row_obj: MyRowObject): |
| 30 | + """Demonstrates an object formatter function""" |
| 31 | + return str(row_obj.get_field3() * row_obj.field4) |
| 32 | + |
| 33 | + |
| 34 | +def multiply_tuple(row_obj): |
| 35 | + """Demonstrates an object formatter function""" |
| 36 | + return str(row_obj[2] * row_obj[3]) |
| 37 | + |
| 38 | + |
| 39 | +def int2word(num, separator="-"): |
| 40 | + """Demonstrates a field formatter function |
| 41 | + From: https://codereview.stackexchange.com/questions/156590/create-the-english-word-for-a-number |
| 42 | + """ |
| 43 | + ones_and_teens = {0: "Zero", 1: 'One', 2: 'Two', 3: 'Three', |
| 44 | + 4: 'Four', 5: 'Five', 6: 'Six', 7: 'Seven', |
| 45 | + 8: 'Eight', 9: 'Nine', 10: 'Ten', 11: 'Eleven', |
| 46 | + 12: 'Twelve', 13: 'Thirteen', 14: 'Fourteen', |
| 47 | + 15: 'Fifteen', 16: 'Sixteen', 17: 'Seventeen', |
| 48 | + 18: 'Eighteen', 19: 'Nineteen'} |
| 49 | + twenty2ninety = {2: 'Twenty', 3: 'Thirty', 4: 'Forty', 5: 'Fifty', |
| 50 | + 6: 'Sixty', 7: 'Seventy', 8: 'Eighty', 9: 'Ninety', 0: ""} |
| 51 | + |
| 52 | + if 0 <= num < 19: |
| 53 | + return ones_and_teens[num] |
| 54 | + elif 20 <= num <= 99: |
| 55 | + tens, below_ten = divmod(num, 10) |
| 56 | + if below_ten > 0: |
| 57 | + words = twenty2ninety[tens] + separator + \ |
| 58 | + ones_and_teens[below_ten].lower() |
| 59 | + else: |
| 60 | + words = twenty2ninety[tens] |
| 61 | + return words |
| 62 | + |
| 63 | + elif 100 <= num <= 999: |
| 64 | + hundreds, below_hundred = divmod(num, 100) |
| 65 | + tens, below_ten = divmod(below_hundred, 10) |
| 66 | + if below_hundred == 0: |
| 67 | + words = ones_and_teens[hundreds] + separator + "hundred" |
| 68 | + elif below_ten == 0: |
| 69 | + words = ones_and_teens[hundreds] + separator + \ |
| 70 | + "hundred" + separator + twenty2ninety[tens].lower() |
| 71 | + else: |
| 72 | + if tens > 0: |
| 73 | + words = ones_and_teens[hundreds] + separator + "hundred" + separator + twenty2ninety[ |
| 74 | + tens].lower() + separator + ones_and_teens[below_ten].lower() |
| 75 | + else: |
| 76 | + words = ones_and_teens[ |
| 77 | + hundreds] + separator + "hundred" + separator + ones_and_teens[below_ten].lower() |
| 78 | + return words |
| 79 | + |
| 80 | + else: |
| 81 | + print("num out of range") |
| 82 | + |
| 83 | +# These tests insert an R and G prefix at the beginning of cells that would |
| 84 | +# otherwise have a row color defined. This allows us to test the insertion |
| 85 | +# of color escape sequences with no color library installed. |
| 86 | + |
| 87 | + |
| 88 | +def test_fmt_obj_rows(): |
| 89 | + expected = ''' |
| 90 | +╔═══════════╤═══════════════════╤═════╤═══════╤════════════╗ |
| 91 | +║ │ │ Num │ │ ║ |
| 92 | +║ First │ Second │ 1 │ Num 2 │ Multiplied ║ |
| 93 | +╠═══════════╪═══════════════════╪═════╪═══════╪════════════╣ |
| 94 | +║ │ │ 17 │ 4 │ 68 ║ |
| 95 | +║ 123.00 B │ 123 │ 5 │ 56 │ 280 ║ |
| 96 | +║ 123.00 B │ 123 │ 5 │ 56 │ 280 ║ |
| 97 | +║ 12.06 KB │ 12,345 │ 23 │ 8 │ 184 ║ |
| 98 | +║ 11.77 MB │ 12,345,678 │ 4 │ 9 │ 36 ║ |
| 99 | +║ 1.15 GB │ 1,234,567,890 │ 7 │ 5 │ 35 ║ |
| 100 | +║ 1.12 TB │ 1,234,567,890,123 │ 7 │ 5 │ 35 ║ |
| 101 | +╚═══════════╧═══════════════════╧═════╧═══════╧════════════╝ |
| 102 | +'''.lstrip('\n') |
| 103 | + rows = [MyRowObject(None, None, 17, 4), |
| 104 | + MyRowObject('123', '123', 5, 56), |
| 105 | + MyRowObject(123, 123, 5, 56), |
| 106 | + MyRowObject(12345, 12345, 23, 8), |
| 107 | + MyRowObject(12345678, 12345678, 4, 9), |
| 108 | + MyRowObject(1234567890, 1234567890, 7, 5), |
| 109 | + MyRowObject(1234567890123, 1234567890123, 7, 5)] |
| 110 | + |
| 111 | + columns = (tf.Column('First', width=20, attrib='field1', formatter=tf.FormatBytes(), |
| 112 | + cell_halign=tf.ColumnAlignment.AlignRight), |
| 113 | + tf.Column('Second', attrib='field2', formatter=tf.FormatCommas(), |
| 114 | + cell_halign=tf.ColumnAlignment.AlignRight), |
| 115 | + tf.Column('Num 1', width=3, attrib='get_field3'), |
| 116 | + tf.Column('Num 2', attrib='field4'), |
| 117 | + tf.Column('Multiplied', obj_formatter=multiply)) |
| 118 | + table = tf.generate_table(rows, columns) |
| 119 | + assert table == expected |
| 120 | + |
| 121 | + |
| 122 | +def test_fmt_tuple_rows(): |
| 123 | + expected = ''' |
| 124 | +╔═══════════╤═══════════════════╤═══════╤═══════════╤════════════╗ |
| 125 | +║ First │ Second │ Num 1 │ Num 2 │ Multiplied ║ |
| 126 | +╠═══════════╪═══════════════════╪═══════╪═══════════╪════════════╣ |
| 127 | +║ │ │ 17 │ Four │ 68 ║ |
| 128 | +║ 123.00 B │ 123 │ 5 │ Fifty-six │ 280 ║ |
| 129 | +║ 123.00 B │ 123 │ 5 │ Fifty-six │ 280 ║ |
| 130 | +║ 12.06 KB │ 12,345 │ 23 │ Eight │ 184 ║ |
| 131 | +║ 11.77 MB │ 12,345,678 │ 4 │ Nine │ 36 ║ |
| 132 | +║ 1.15 GB │ 1,234,567,890 │ 7 │ Five │ 35 ║ |
| 133 | +║ 1.12 TB │ 1,234,567,890,123 │ 7 │ Five │ 35 ║ |
| 134 | +╚═══════════╧═══════════════════╧═══════╧═══════════╧════════════╝ |
| 135 | +'''.lstrip('\n') |
| 136 | + |
| 137 | + rows = [(None, None, 17, 4, None), |
| 138 | + ('123', '123', 5, 56, None), |
| 139 | + (123, 123, 5, 56, None), |
| 140 | + (12345, 12345, 23, 8, None), |
| 141 | + (12345678, 12345678, 4, 9, None), |
| 142 | + (1234567890, 1234567890, 7, 5, None), |
| 143 | + (1234567890123, 1234567890123, 7, 5, None)] |
| 144 | + |
| 145 | + columns = (tf.Column('First', width=20, formatter=tf.FormatBytes(), cell_halign=tf.ColumnAlignment.AlignRight), |
| 146 | + tf.Column('Second', formatter=tf.FormatCommas(), cell_halign=tf.ColumnAlignment.AlignRight), |
| 147 | + tf.Column('Num 1'), |
| 148 | + tf.Column('Num 2', formatter=int2word), |
| 149 | + tf.Column('Multiplied', obj_formatter=multiply_tuple)) |
| 150 | + |
| 151 | + table = tf.generate_table(rows, columns) |
| 152 | + |
| 153 | + assert table == expected |
0 commit comments