teddecor.UnitTest.Results

Results

TestResults, ClassResults, and SuiteResults all hold and translate the test result information into a structure that is easy to use and has mutliple outputs.

  1"""Results
  2
  3TestResults, ClassResults, and SuiteResults all hold and translate the test result information
  4into a structure that is easy to use and has mutliple outputs.
  5"""
  6from __future__ import annotations
  7from dataclasses import dataclass
  8from typing import Union
  9
 10from ..Util import slash
 11from ..TED.markup import TED
 12from .Objects import TestFilter
 13
 14__all__ = [
 15    "TestResult",
 16    "ClassResult",
 17    "SuiteResult",
 18    "SaveType",
 19    "ResultType",
 20    "RunResults",
 21]
 22
 23
 24@dataclass
 25class ResultType:
 26    """Enum/Dataclass that describes the test run result.
 27
 28    Attributes:
 29        SUCCESS (tuple[str, str]): Message and color for a successful test run
 30        FAILED (tuple[str, str]): Message and color for a failed test run
 31        SKIPPED (tuple[str, str]): Message and color for a skipped test run
 32    """
 33
 34    SUCCESS: tuple[str, str, int] = ("Passed", "[@F green]", "✓")
 35    FAILED: tuple[str, str, int] = ("Failed", "[@F red]", "x")
 36    SKIPPED: tuple[str, str, int] = ("Skipped", "[@F yellow]", "↻")
 37
 38
 39@dataclass
 40class SaveType:
 41    """Enum/Dataclass that describes the save file extension/type.
 42
 43    Attributes:
 44        CSV (str): `.csv` Save results as a CSV file
 45        JSON (str): `.json` Save results as a JSON file
 46        TXT (str):  `.txt` Save results as a TXT file
 47    """
 48
 49    CSV: str = ".csv"
 50    JSON: str = ".json"
 51    TXT: str = ".txt"
 52    ALL: callable = lambda: [".txt", ".json", ".csv"]
 53
 54
 55class Result:
 56    """Base class for result types"""
 57
 58    def __init__(self):
 59        self._counts = [0, 0, 0]
 60
 61    @property
 62    def counts(self) -> tuple[int, int, int]:
 63        """Get counts for passed, failed, skipped.
 64
 65        Returns:
 66            tuple: The values for passed, failed, skipped respectively
 67        """
 68        return tuple(self._counts)
 69
 70    @property
 71    def name(self) -> str:
 72        return self._name
 73
 74    def write(self, indent: int = 0):
 75        """Output the result(s) to the screen
 76
 77        Args:
 78            indent (int, optional): The amount to indent the values. Defaults to 0.
 79        """
 80        for line in self.pretty(indent):
 81            TED.print(line)
 82
 83    def pretty(self, indent: int) -> list:
 84        """Format the result(s) into a formatted list
 85
 86        Returns:
 87            list: List of formatted result(s)
 88        """
 89        return []
 90
 91    def dict(self) -> dict:
 92        """Generate the dictionary varient of the results
 93
 94        Returns:
 95            dict: The results formatted as a dictionary
 96        """
 97        return {}
 98
 99    def isdir(self, location: str) -> Union[str, None]:
100        """Takes the location that the file is to be saved then changes directory.
101
102        Args:
103            location (str, optional): The location where the file will be saved. Defaults to None.
104
105        Returns:
106            str, None: The absolute path or None if path doesn't exist
107
108        Note:
109            This is to be used with an inherited class and will auto convert `~` to it's absolute path
110        """
111
112        if location != "":
113            from os import path
114
115            if location.startswith("~"):
116                from pathlib import Path
117
118                location = str(Path.home()) + location[1:]
119
120            if not path.isdir(location):
121                return None
122
123            if not location.endswith(slash()):
124                location += slash()
125
126        return location
127
128    def __str__(self):
129        return "\n".join(self.pretty())
130
131    def __repr__(self):
132        return "\n".join(self.str())
133
134
135class TestResult(Result):
136    def __init__(self, result: tuple[str, ResultType, Union[str, list]] = None):
137        super().__init__()
138
139        if result is not None:
140            self._name = result[0]
141            self._result = result[1]
142            self._info = result[2]
143        else:
144            self._name = "Unknown"
145            self._result = ResultType.SKIPPED
146            self._info = "Unkown test"
147
148        if result[1] == ResultType.SUCCESS:
149            self._counts[0] += 1
150        elif result[1] == ResultType.FAILED:
151            self._counts[1] += 1
152        elif result[1] == ResultType.SKIPPED:
153            self._counts[2] += 1
154
155    @property
156    def result(self) -> str:
157        return self._result[0]
158
159    @property
160    def color(self) -> str:
161        return self._result[1]
162
163    @property
164    def icon(self) -> str:
165        return self._result[2]
166
167    @property
168    def info(self) -> Union[str, list]:
169        return self._info
170
171    def pretty(self, indent: int = 0) -> list:
172        """Used to convert results into a list of strings. Allows for additional indentation to be added.
173
174        Args:
175            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
176
177        Returns:
178            list: The formatted results as a list of string with indents
179        """
180        out = []
181        out.append(
182            "".ljust(indent, " ")
183            + f"\[{self.color}{self.icon}[@F]] {TED.encode(self.name)}"
184        )
185        if isinstance(self.info, list):
186            for trace in self.info:
187                out.append("".ljust(indent + 4, " ") + trace)
188        else:
189            if self.info != "":
190                out.append("".ljust(indent + 4, " ") + self.info)
191
192        return out
193
194    def str(self, indent: int = 0) -> list:
195        """Results formatted into lines without colors
196
197        Args:
198            indent (int, optional): The amount to indent the lines. Defaults to 0.
199
200        Returns:
201            list: The results as lines
202        """
203        out = []
204        out.append(" " * indent + f"[{self.icon}] {self.name}")
205        if isinstance(self.info, list):
206            for trace in self.info:
207                out.append(" " * (indent + 4) + TED.strip(trace))
208        else:
209            if self.info != "":
210                out.append(" " * (indent + 4) + self.info)
211
212        return out
213
214    def dict(self) -> dict:
215        """Convert the test result into a dictionary
216
217        Returns:
218            dict: Dictionary format of the test result
219        """
220        return {self.name: {"result": self._result[0], "info": self.info}}
221
222    def csv(self) -> str:
223        """The results formatted as CSV
224
225        Returns:
226            str: CSV format of the result
227        """
228        info = "\n".join(self.info) if isinstance(self.info, list) else self.info
229        return f'{self.name},{self.result},"{info}"'
230
231    def save(
232        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
233    ) -> bool:
234        """Takes a file location and creates a json file with the test data
235
236        Args:
237            location (str, optional): The location where the json file will be created. Defaults to "".
238
239        Returns:
240            bool: True if the file was successfully created
241        """
242
243        location = self.isdir(location)
244
245        if isinstance(ext, str):
246            self.__save_to_file(location, ext)
247        elif isinstance(ext, list):
248            for ext in ext:
249                self.__save_to_file(location, ext)
250        return True
251
252    def __save_to_file(self, location: str, type: str) -> bool:
253        """Saves the data to a given file type in a given location
254
255        Args:
256            location (str): Where to save the file
257            type (str): Type of file to save, CSV, JSON, TXT
258
259        Returns:
260            bool: True if file was saved
261        """
262        if location is not None:
263            with open(location + self.name + type, "+w", encoding="utf-8") as file:
264                if type == SaveType.CSV:
265                    file.write("Test Case,result,info\n")
266                    file.write(self.csv())
267                    return True
268                elif type == SaveType.JSON:
269                    from json import dumps
270
271                    file.write(dumps(self.dict(), indent=2))
272                    return True
273                elif type == SaveType.TXT:
274                    file.write(repr(self))
275                    return True
276        else:
277            return False
278
279
280class ClassResult(Result):
281    def __init__(self, name: str, results: list[TestResult] = None):
282        super().__init__()
283
284        self._results = []
285        if results is not None:
286            for result in results:
287                self.append(result)
288
289        self._name = name
290
291    @property
292    def results(self) -> list:
293        return self._results
294
295    def append(self, result: TestResult):
296        """Add a result to the list of results. This will also increment the counts.
297
298        Args:
299            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
300        """
301        passed, failed, skipped = result.counts
302        self._counts[0] += passed
303        self._counts[1] += failed
304        self._counts[2] += skipped
305
306        self._results.append(result)
307
308    def pretty(self, indent: int = 0) -> list:
309        """Used to convert results into a list of strings. Allows for additional indentation to be added.
310
311        Args:
312            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
313
314        Returns:
315            list: The formatted results as a list of string with indents
316        """
317
318        out = []
319
320        passed, failed, skipped = self.counts
321        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
322:{ResultType.FAILED[1]}{failed}[@F]]"
323        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
324
325        if len(self.results):
326            for result in self.results:
327                out.extend(result.pretty(indent + 4))
328        else:
329            out.append(
330                " " * (indent + 4)
331                + f"[@F yellow]No Tests Found for {TED.encode(self.name)}"
332            )
333
334        return out
335
336    def str(self, indent: int = 0) -> list:
337        """Results formatted into lines without colors
338
339        Args:
340            indent (int, optional): The amount to indent the lines. Defaults to 0.
341
342        Returns:
343            list: The results as lines
344        """
345        out = []
346
347        passed, failed, skipped = self.counts
348        out.append(" " * indent + f"[C:{passed}:{skipped}:{failed}] {self.name}")
349
350        if len(self.results):
351            for result in self.results:
352                out.extend(result.str(indent + 4))
353        else:
354            out.append(" " * (indent + 4) + f"No Tests Found for {self.name}")
355
356        return out
357
358    def dict(self) -> dict:
359        """Convert the test result into a dictionary
360
361        Returns:
362            dict: Dictionary format of the test result
363        """
364
365        out = {self.name: {}}
366
367        for result in self.results:
368            out[self.name].update(result.dict())
369
370        return out
371
372    def csv(self) -> list:
373        """The test case results. Each index is a different line in the file
374
375        Returns:
376            list: The lines to be written to a CSV file
377        """
378
379        out = []
380
381        for result in self.results:
382            out.append(f"{self.name}," + result.csv())
383
384        return out
385
386    def save(
387        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
388    ) -> bool:
389        """Takes a file location and creates a json file with the test data
390
391        Args:
392            location (str, optional): The location where the json file will be created. Defaults to "".
393
394        Returns:
395            bool: True if the file was successfully created
396        """
397
398        location = self.isdir(location)
399
400        if isinstance(ext, str):
401            self.__save_to_file(location, ext)
402        elif isinstance(ext, list):
403            for ext in ext:
404                self.__save_to_file(location, ext)
405        return True
406
407    def __save_to_file(self, location: str, type: str) -> bool:
408        """Saves the data to a given file type in a given location
409
410        Args:
411            location (str): Where to save the file
412            type (str): Type of file to save, CSV, JSON, TXT
413
414        Returns:
415            bool: True if file was saved
416        """
417        if location is not None:
418            with open(location + self.name + type, "+w", encoding="utf-8") as file:
419                if type == SaveType.CSV:
420                    file.write("Test Class,Test Case,Result,Info\n")
421                    for line in self.csv():
422                        file.write(f"{line}\n")
423                    return True
424                elif type == SaveType.JSON:
425                    from json import dumps
426
427                    file.write(dumps(self.dict(), indent=2))
428                    return True
429                elif type == SaveType.TXT:
430                    file.write(repr(self))
431                    return True
432        else:
433            return False
434
435
436class SuiteResult(Result):
437    def __init__(self, name: str):
438        super().__init__()
439
440        self._name = name
441        self._results = []
442
443    @property
444    def results(self) -> list:
445        return self._results
446
447    def append(self, result: Union[TestResult, ClassResult]):
448        """Add a result to the list of results. This will also increment the counts.
449
450        Args:
451            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
452        """
453        passed, failed, skipped = result.counts
454        self._counts[0] += passed
455        self._counts[1] += failed
456        self._counts[2] += skipped
457
458        self._results.append(result)
459
460    def pretty(self, indent: int = 0) -> list:
461        """Used to convert results into a list of strings. Allows for additional indentation to be added.
462
463        Args:
464            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
465
466        Returns:
467            list: The formatted results as a list of string with indents
468        """
469
470        out = []
471
472        passed, failed, skipped = self.counts
473        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
474:{ResultType.FAILED[1]}{failed}[@F]]"
475        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
476
477        if len(self.results):
478            for result in self.results:
479                out.extend(result.pretty(indent + 4))
480        else:
481            out.append(
482                " " * (indent + 4)
483                + f"[@Fyellow]No tests found for {TED.encode(self.name)}"
484            )
485
486        return out
487
488    def str(self, indent: int = 0) -> list:
489        """Results formatted into lines without colors
490
491        Args:
492            indent (int, optional): The amount to indent the lines. Defaults to 0.
493
494        Returns:
495            list: The results as lines
496        """
497        out = []
498
499        passed, failed, skipped = self.counts
500        out.append(" " * indent + f"[S:{passed}:{skipped}:{failed}] {self.name}")
501
502        if len(self.results):
503            for result in self.results:
504                out.extend(result.str(indent + 4))
505        else:
506            out.append(" " * (indent + 4) + f"No tests found for {self.name}")
507
508        return out
509
510    def dict(self) -> dict:
511        """Convert the test result into a dictionary
512
513        Returns:
514            dict: Dictionary format of the test result
515        """
516
517        out = {self.name: {}}
518
519        for result in self.results:
520            out[self.name].update(result.dict())
521
522        return out
523
524    def csv(self) -> list:
525        """The test case results. Each index is a different line in the file
526
527        Returns:
528            list: The lines to be written to a CSV file
529        """
530
531        out = []
532
533        for result in self.results:
534            if isinstance(result.csv(), list):
535                for line in result.csv():
536                    out.append(f"{self.name}," + line)
537            else:
538                out.append(f"{self.name},," + result.csv())
539
540        return out
541
542    def save(
543        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
544    ) -> bool:
545        """Takes a file location and creates a json file with the test data
546
547        Args:
548            location (str, optional): The location where the json file will be created. Defaults to "".
549
550        Returns:
551            bool: True if the file was successfully created
552        """
553
554        location = self.isdir(location)
555
556        if isinstance(ext, str):
557            self.__save_to_file(location, ext)
558        elif isinstance(ext, list):
559            for ext in ext:
560                self.__save_to_file(location, ext)
561        return True
562
563    def __save_to_file(self, location: str, type: str) -> bool:
564        """Saves the data to a given file type in a given location
565
566        Args:
567            location (str): Where to save the file
568            type (str): Type of file to save, CSV, JSON, TXT
569
570        Returns:
571            bool: True if file was saved
572        """
573
574        if location is not None:
575            with open(location + self.name + type, "+w", encoding="utf-8") as file:
576                if type == SaveType.CSV:
577                    file.write("Test Suite, Test Class,Test Case,Result,Info\n")
578                    for line in self.csv():
579                        file.write(f"{line}\n")
580                    return True
581                elif type == SaveType.JSON:
582                    from json import dumps
583
584                    file.write(dumps(self.dict(), indent=2))
585                    return True
586                elif type == SaveType.TXT:
587                    file.write(repr(self))
588                    return True
589        else:
590            return False
591
592    def __str__(self):
593        return "\n".join(self.pretty())
594
595    def __repr__(self):
596        return "\n".join(self.str())
597
598
599class RunResults(Result):
600    def __init__(self, name: str = "TestRun"):
601        super().__init__()
602
603        self._name = name
604        self._results = []
605
606    @property
607    def results(self) -> list:
608        return self._results
609
610    def append(self, result: SuiteResult):
611        """Add a result to the list of results. This will also increment the counts.
612
613        Args:
614            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
615        """
616        passed, failed, skipped = result.counts
617        self._counts[0] += passed
618        self._counts[1] += failed
619        self._counts[2] += skipped
620
621        self._results.append(result)
622
623    def pretty(self, indent: int = 0) -> list:
624        """Used to convert results into a list of strings. Allows for additional indentation to be added.
625
626        Args:
627            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
628
629        Returns:
630            list: The formatted results as a list of string with indents
631        """
632
633        out = []
634
635        passed, failed, skipped = self.counts
636        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
637:{ResultType.FAILED[1]}{failed}[@F]]"
638        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
639
640        if len(self.results):
641            for result in self.results:
642                out.extend(result.pretty(indent + 4))
643        else:
644            out.append(" " * (indent + 4) + f"[@Fyellow]No tests found for current run")
645
646        return out
647
648    def str(self, indent: int = 0) -> list:
649        """Results formatted into lines without colors
650
651        Args:
652            indent (int, optional): The amount to indent the lines. Defaults to 0.
653
654        Returns:
655            list: The results as lines
656        """
657        out = []
658
659        passed, failed, skipped = self.counts
660        out.append(" " * indent + f"[R:{passed}:{skipped}:{failed}] {self.name}")
661
662        if len(self.results):
663            for result in self.results:
664                out.extend(result.str(indent + 4))
665        else:
666            out.append(" " * (indent + 4) + f"No tests found for current run")
667
668        return out
669
670    def dict(self) -> dict:
671        """Convert the test result into a dictionary
672
673        Returns:
674            dict: Dictionary format of the test result
675        """
676
677        out = {self.name: {}}
678
679        for result in self.results:
680            out[self.name].update(result.dict())
681
682        return out
683
684    def csv(self) -> list:
685        """The test case results. Each index is a different line in the file
686
687        Returns:
688            list: The lines to be written to a CSV file
689        """
690
691        out = []
692
693        for result in self.results:
694            out.extend(result.csv())
695
696        return out
697
698    def save(
699        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
700    ) -> bool:
701        """Takes a file location and creates a json file with the test data
702
703        Args:
704            location (str, optional): The location where the json file will be created. Defaults to "".
705
706        Returns:
707            bool: True if the file was successfully created
708        """
709
710        location = self.isdir(location)
711
712        if isinstance(ext, str):
713            self.__save_to_file(location, ext)
714        elif isinstance(ext, list):
715            for ext in ext:
716                self.__save_to_file(location, ext)
717        return True
718
719    def __save_to_file(self, location: str, type: str) -> bool:
720        """Saves the data to a given file type in a given location
721
722        Args:
723            location (str): Where to save the file
724            type (str): Type of file to save, CSV, JSON, TXT
725
726        Returns:
727            bool: True if file was saved
728        """
729
730        if location is not None:
731            with open(location + self.name + type, "+w", encoding="utf-8") as file:
732                if type == SaveType.CSV:
733                    file.write("Test Suite, Test Class,Test Case,Result,Info\n")
734                    for line in self.csv():
735                        file.write(f"{line}\n")
736                    return True
737                elif type == SaveType.JSON:
738                    from json import dumps
739
740                    file.write(dumps(self.dict(), indent=2))
741                    return True
742                elif type == SaveType.TXT:
743                    file.write(repr(self))
744                    return True
745        else:
746            return False
747
748    def __str__(self):
749        return "\n".join(self.pretty())
750
751    def __repr__(self):
752        return "\n".join(self.str())
class TestResult(Result):
136class TestResult(Result):
137    def __init__(self, result: tuple[str, ResultType, Union[str, list]] = None):
138        super().__init__()
139
140        if result is not None:
141            self._name = result[0]
142            self._result = result[1]
143            self._info = result[2]
144        else:
145            self._name = "Unknown"
146            self._result = ResultType.SKIPPED
147            self._info = "Unkown test"
148
149        if result[1] == ResultType.SUCCESS:
150            self._counts[0] += 1
151        elif result[1] == ResultType.FAILED:
152            self._counts[1] += 1
153        elif result[1] == ResultType.SKIPPED:
154            self._counts[2] += 1
155
156    @property
157    def result(self) -> str:
158        return self._result[0]
159
160    @property
161    def color(self) -> str:
162        return self._result[1]
163
164    @property
165    def icon(self) -> str:
166        return self._result[2]
167
168    @property
169    def info(self) -> Union[str, list]:
170        return self._info
171
172    def pretty(self, indent: int = 0) -> list:
173        """Used to convert results into a list of strings. Allows for additional indentation to be added.
174
175        Args:
176            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
177
178        Returns:
179            list: The formatted results as a list of string with indents
180        """
181        out = []
182        out.append(
183            "".ljust(indent, " ")
184            + f"\[{self.color}{self.icon}[@F]] {TED.encode(self.name)}"
185        )
186        if isinstance(self.info, list):
187            for trace in self.info:
188                out.append("".ljust(indent + 4, " ") + trace)
189        else:
190            if self.info != "":
191                out.append("".ljust(indent + 4, " ") + self.info)
192
193        return out
194
195    def str(self, indent: int = 0) -> list:
196        """Results formatted into lines without colors
197
198        Args:
199            indent (int, optional): The amount to indent the lines. Defaults to 0.
200
201        Returns:
202            list: The results as lines
203        """
204        out = []
205        out.append(" " * indent + f"[{self.icon}] {self.name}")
206        if isinstance(self.info, list):
207            for trace in self.info:
208                out.append(" " * (indent + 4) + TED.strip(trace))
209        else:
210            if self.info != "":
211                out.append(" " * (indent + 4) + self.info)
212
213        return out
214
215    def dict(self) -> dict:
216        """Convert the test result into a dictionary
217
218        Returns:
219            dict: Dictionary format of the test result
220        """
221        return {self.name: {"result": self._result[0], "info": self.info}}
222
223    def csv(self) -> str:
224        """The results formatted as CSV
225
226        Returns:
227            str: CSV format of the result
228        """
229        info = "\n".join(self.info) if isinstance(self.info, list) else self.info
230        return f'{self.name},{self.result},"{info}"'
231
232    def save(
233        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
234    ) -> bool:
235        """Takes a file location and creates a json file with the test data
236
237        Args:
238            location (str, optional): The location where the json file will be created. Defaults to "".
239
240        Returns:
241            bool: True if the file was successfully created
242        """
243
244        location = self.isdir(location)
245
246        if isinstance(ext, str):
247            self.__save_to_file(location, ext)
248        elif isinstance(ext, list):
249            for ext in ext:
250                self.__save_to_file(location, ext)
251        return True
252
253    def __save_to_file(self, location: str, type: str) -> bool:
254        """Saves the data to a given file type in a given location
255
256        Args:
257            location (str): Where to save the file
258            type (str): Type of file to save, CSV, JSON, TXT
259
260        Returns:
261            bool: True if file was saved
262        """
263        if location is not None:
264            with open(location + self.name + type, "+w", encoding="utf-8") as file:
265                if type == SaveType.CSV:
266                    file.write("Test Case,result,info\n")
267                    file.write(self.csv())
268                    return True
269                elif type == SaveType.JSON:
270                    from json import dumps
271
272                    file.write(dumps(self.dict(), indent=2))
273                    return True
274                elif type == SaveType.TXT:
275                    file.write(repr(self))
276                    return True
277        else:
278            return False

Base class for result types

TestResult( result: tuple[str, teddecor.UnitTest.Results.ResultType, typing.Union[str, list]] = None)
137    def __init__(self, result: tuple[str, ResultType, Union[str, list]] = None):
138        super().__init__()
139
140        if result is not None:
141            self._name = result[0]
142            self._result = result[1]
143            self._info = result[2]
144        else:
145            self._name = "Unknown"
146            self._result = ResultType.SKIPPED
147            self._info = "Unkown test"
148
149        if result[1] == ResultType.SUCCESS:
150            self._counts[0] += 1
151        elif result[1] == ResultType.FAILED:
152            self._counts[1] += 1
153        elif result[1] == ResultType.SKIPPED:
154            self._counts[2] += 1
result: str
color: str
icon: str
info: Union[str, list]
def pretty(self, indent: int = 0) -> list:
172    def pretty(self, indent: int = 0) -> list:
173        """Used to convert results into a list of strings. Allows for additional indentation to be added.
174
175        Args:
176            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
177
178        Returns:
179            list: The formatted results as a list of string with indents
180        """
181        out = []
182        out.append(
183            "".ljust(indent, " ")
184            + f"\[{self.color}{self.icon}[@F]] {TED.encode(self.name)}"
185        )
186        if isinstance(self.info, list):
187            for trace in self.info:
188                out.append("".ljust(indent + 4, " ") + trace)
189        else:
190            if self.info != "":
191                out.append("".ljust(indent + 4, " ") + self.info)
192
193        return out

Used to convert results into a list of strings. Allows for additional indentation to be added.

Args: indent (int, optional): Amount of indent to add in spaces. Defaults to 0.

Returns: list: The formatted results as a list of string with indents

def str(self, indent: int = 0) -> list:
195    def str(self, indent: int = 0) -> list:
196        """Results formatted into lines without colors
197
198        Args:
199            indent (int, optional): The amount to indent the lines. Defaults to 0.
200
201        Returns:
202            list: The results as lines
203        """
204        out = []
205        out.append(" " * indent + f"[{self.icon}] {self.name}")
206        if isinstance(self.info, list):
207            for trace in self.info:
208                out.append(" " * (indent + 4) + TED.strip(trace))
209        else:
210            if self.info != "":
211                out.append(" " * (indent + 4) + self.info)
212
213        return out

Results formatted into lines without colors

Args: indent (int, optional): The amount to indent the lines. Defaults to 0.

Returns: list: The results as lines

def dict(self) -> dict:
215    def dict(self) -> dict:
216        """Convert the test result into a dictionary
217
218        Returns:
219            dict: Dictionary format of the test result
220        """
221        return {self.name: {"result": self._result[0], "info": self.info}}

Convert the test result into a dictionary

Returns: dict: Dictionary format of the test result

def csv(self) -> str:
223    def csv(self) -> str:
224        """The results formatted as CSV
225
226        Returns:
227            str: CSV format of the result
228        """
229        info = "\n".join(self.info) if isinstance(self.info, list) else self.info
230        return f'{self.name},{self.result},"{info}"'

The results formatted as CSV

Returns: str: CSV format of the result

def save(self, location: str = '', ext: Union[str, list[str]] = '.csv') -> bool:
232    def save(
233        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
234    ) -> bool:
235        """Takes a file location and creates a json file with the test data
236
237        Args:
238            location (str, optional): The location where the json file will be created. Defaults to "".
239
240        Returns:
241            bool: True if the file was successfully created
242        """
243
244        location = self.isdir(location)
245
246        if isinstance(ext, str):
247            self.__save_to_file(location, ext)
248        elif isinstance(ext, list):
249            for ext in ext:
250                self.__save_to_file(location, ext)
251        return True

Takes a file location and creates a json file with the test data

Args: location (str, optional): The location where the json file will be created. Defaults to "".

Returns: bool: True if the file was successfully created

Inherited Members
Result
counts
name
write
isdir
class ClassResult(Result):
281class ClassResult(Result):
282    def __init__(self, name: str, results: list[TestResult] = None):
283        super().__init__()
284
285        self._results = []
286        if results is not None:
287            for result in results:
288                self.append(result)
289
290        self._name = name
291
292    @property
293    def results(self) -> list:
294        return self._results
295
296    def append(self, result: TestResult):
297        """Add a result to the list of results. This will also increment the counts.
298
299        Args:
300            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
301        """
302        passed, failed, skipped = result.counts
303        self._counts[0] += passed
304        self._counts[1] += failed
305        self._counts[2] += skipped
306
307        self._results.append(result)
308
309    def pretty(self, indent: int = 0) -> list:
310        """Used to convert results into a list of strings. Allows for additional indentation to be added.
311
312        Args:
313            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
314
315        Returns:
316            list: The formatted results as a list of string with indents
317        """
318
319        out = []
320
321        passed, failed, skipped = self.counts
322        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
323:{ResultType.FAILED[1]}{failed}[@F]]"
324        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
325
326        if len(self.results):
327            for result in self.results:
328                out.extend(result.pretty(indent + 4))
329        else:
330            out.append(
331                " " * (indent + 4)
332                + f"[@F yellow]No Tests Found for {TED.encode(self.name)}"
333            )
334
335        return out
336
337    def str(self, indent: int = 0) -> list:
338        """Results formatted into lines without colors
339
340        Args:
341            indent (int, optional): The amount to indent the lines. Defaults to 0.
342
343        Returns:
344            list: The results as lines
345        """
346        out = []
347
348        passed, failed, skipped = self.counts
349        out.append(" " * indent + f"[C:{passed}:{skipped}:{failed}] {self.name}")
350
351        if len(self.results):
352            for result in self.results:
353                out.extend(result.str(indent + 4))
354        else:
355            out.append(" " * (indent + 4) + f"No Tests Found for {self.name}")
356
357        return out
358
359    def dict(self) -> dict:
360        """Convert the test result into a dictionary
361
362        Returns:
363            dict: Dictionary format of the test result
364        """
365
366        out = {self.name: {}}
367
368        for result in self.results:
369            out[self.name].update(result.dict())
370
371        return out
372
373    def csv(self) -> list:
374        """The test case results. Each index is a different line in the file
375
376        Returns:
377            list: The lines to be written to a CSV file
378        """
379
380        out = []
381
382        for result in self.results:
383            out.append(f"{self.name}," + result.csv())
384
385        return out
386
387    def save(
388        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
389    ) -> bool:
390        """Takes a file location and creates a json file with the test data
391
392        Args:
393            location (str, optional): The location where the json file will be created. Defaults to "".
394
395        Returns:
396            bool: True if the file was successfully created
397        """
398
399        location = self.isdir(location)
400
401        if isinstance(ext, str):
402            self.__save_to_file(location, ext)
403        elif isinstance(ext, list):
404            for ext in ext:
405                self.__save_to_file(location, ext)
406        return True
407
408    def __save_to_file(self, location: str, type: str) -> bool:
409        """Saves the data to a given file type in a given location
410
411        Args:
412            location (str): Where to save the file
413            type (str): Type of file to save, CSV, JSON, TXT
414
415        Returns:
416            bool: True if file was saved
417        """
418        if location is not None:
419            with open(location + self.name + type, "+w", encoding="utf-8") as file:
420                if type == SaveType.CSV:
421                    file.write("Test Class,Test Case,Result,Info\n")
422                    for line in self.csv():
423                        file.write(f"{line}\n")
424                    return True
425                elif type == SaveType.JSON:
426                    from json import dumps
427
428                    file.write(dumps(self.dict(), indent=2))
429                    return True
430                elif type == SaveType.TXT:
431                    file.write(repr(self))
432                    return True
433        else:
434            return False

Base class for result types

ClassResult( name: str, results: list[teddecor.UnitTest.Results.TestResult] = None)
282    def __init__(self, name: str, results: list[TestResult] = None):
283        super().__init__()
284
285        self._results = []
286        if results is not None:
287            for result in results:
288                self.append(result)
289
290        self._name = name
results: list
def append(self, result: teddecor.UnitTest.Results.TestResult)
296    def append(self, result: TestResult):
297        """Add a result to the list of results. This will also increment the counts.
298
299        Args:
300            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
301        """
302        passed, failed, skipped = result.counts
303        self._counts[0] += passed
304        self._counts[1] += failed
305        self._counts[2] += skipped
306
307        self._results.append(result)

Add a result to the list of results. This will also increment the counts.

Args: result (Union[TestResult, ClassResult]): The result to add to the colleciton of results

def pretty(self, indent: int = 0) -> list:
309    def pretty(self, indent: int = 0) -> list:
310        """Used to convert results into a list of strings. Allows for additional indentation to be added.
311
312        Args:
313            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
314
315        Returns:
316            list: The formatted results as a list of string with indents
317        """
318
319        out = []
320
321        passed, failed, skipped = self.counts
322        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
323:{ResultType.FAILED[1]}{failed}[@F]]"
324        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
325
326        if len(self.results):
327            for result in self.results:
328                out.extend(result.pretty(indent + 4))
329        else:
330            out.append(
331                " " * (indent + 4)
332                + f"[@F yellow]No Tests Found for {TED.encode(self.name)}"
333            )
334
335        return out

Used to convert results into a list of strings. Allows for additional indentation to be added.

Args: indent (int, optional): Amount of indent to add in spaces. Defaults to 0.

Returns: list: The formatted results as a list of string with indents

def str(self, indent: int = 0) -> list:
337    def str(self, indent: int = 0) -> list:
338        """Results formatted into lines without colors
339
340        Args:
341            indent (int, optional): The amount to indent the lines. Defaults to 0.
342
343        Returns:
344            list: The results as lines
345        """
346        out = []
347
348        passed, failed, skipped = self.counts
349        out.append(" " * indent + f"[C:{passed}:{skipped}:{failed}] {self.name}")
350
351        if len(self.results):
352            for result in self.results:
353                out.extend(result.str(indent + 4))
354        else:
355            out.append(" " * (indent + 4) + f"No Tests Found for {self.name}")
356
357        return out

Results formatted into lines without colors

Args: indent (int, optional): The amount to indent the lines. Defaults to 0.

Returns: list: The results as lines

def dict(self) -> dict:
359    def dict(self) -> dict:
360        """Convert the test result into a dictionary
361
362        Returns:
363            dict: Dictionary format of the test result
364        """
365
366        out = {self.name: {}}
367
368        for result in self.results:
369            out[self.name].update(result.dict())
370
371        return out

Convert the test result into a dictionary

Returns: dict: Dictionary format of the test result

def csv(self) -> list:
373    def csv(self) -> list:
374        """The test case results. Each index is a different line in the file
375
376        Returns:
377            list: The lines to be written to a CSV file
378        """
379
380        out = []
381
382        for result in self.results:
383            out.append(f"{self.name}," + result.csv())
384
385        return out

The test case results. Each index is a different line in the file

Returns: list: The lines to be written to a CSV file

def save(self, location: str = '', ext: Union[str, list[str]] = '.csv') -> bool:
387    def save(
388        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
389    ) -> bool:
390        """Takes a file location and creates a json file with the test data
391
392        Args:
393            location (str, optional): The location where the json file will be created. Defaults to "".
394
395        Returns:
396            bool: True if the file was successfully created
397        """
398
399        location = self.isdir(location)
400
401        if isinstance(ext, str):
402            self.__save_to_file(location, ext)
403        elif isinstance(ext, list):
404            for ext in ext:
405                self.__save_to_file(location, ext)
406        return True

Takes a file location and creates a json file with the test data

Args: location (str, optional): The location where the json file will be created. Defaults to "".

Returns: bool: True if the file was successfully created

Inherited Members
Result
counts
name
write
isdir
class SuiteResult(Result):
437class SuiteResult(Result):
438    def __init__(self, name: str):
439        super().__init__()
440
441        self._name = name
442        self._results = []
443
444    @property
445    def results(self) -> list:
446        return self._results
447
448    def append(self, result: Union[TestResult, ClassResult]):
449        """Add a result to the list of results. This will also increment the counts.
450
451        Args:
452            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
453        """
454        passed, failed, skipped = result.counts
455        self._counts[0] += passed
456        self._counts[1] += failed
457        self._counts[2] += skipped
458
459        self._results.append(result)
460
461    def pretty(self, indent: int = 0) -> list:
462        """Used to convert results into a list of strings. Allows for additional indentation to be added.
463
464        Args:
465            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
466
467        Returns:
468            list: The formatted results as a list of string with indents
469        """
470
471        out = []
472
473        passed, failed, skipped = self.counts
474        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
475:{ResultType.FAILED[1]}{failed}[@F]]"
476        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
477
478        if len(self.results):
479            for result in self.results:
480                out.extend(result.pretty(indent + 4))
481        else:
482            out.append(
483                " " * (indent + 4)
484                + f"[@Fyellow]No tests found for {TED.encode(self.name)}"
485            )
486
487        return out
488
489    def str(self, indent: int = 0) -> list:
490        """Results formatted into lines without colors
491
492        Args:
493            indent (int, optional): The amount to indent the lines. Defaults to 0.
494
495        Returns:
496            list: The results as lines
497        """
498        out = []
499
500        passed, failed, skipped = self.counts
501        out.append(" " * indent + f"[S:{passed}:{skipped}:{failed}] {self.name}")
502
503        if len(self.results):
504            for result in self.results:
505                out.extend(result.str(indent + 4))
506        else:
507            out.append(" " * (indent + 4) + f"No tests found for {self.name}")
508
509        return out
510
511    def dict(self) -> dict:
512        """Convert the test result into a dictionary
513
514        Returns:
515            dict: Dictionary format of the test result
516        """
517
518        out = {self.name: {}}
519
520        for result in self.results:
521            out[self.name].update(result.dict())
522
523        return out
524
525    def csv(self) -> list:
526        """The test case results. Each index is a different line in the file
527
528        Returns:
529            list: The lines to be written to a CSV file
530        """
531
532        out = []
533
534        for result in self.results:
535            if isinstance(result.csv(), list):
536                for line in result.csv():
537                    out.append(f"{self.name}," + line)
538            else:
539                out.append(f"{self.name},," + result.csv())
540
541        return out
542
543    def save(
544        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
545    ) -> bool:
546        """Takes a file location and creates a json file with the test data
547
548        Args:
549            location (str, optional): The location where the json file will be created. Defaults to "".
550
551        Returns:
552            bool: True if the file was successfully created
553        """
554
555        location = self.isdir(location)
556
557        if isinstance(ext, str):
558            self.__save_to_file(location, ext)
559        elif isinstance(ext, list):
560            for ext in ext:
561                self.__save_to_file(location, ext)
562        return True
563
564    def __save_to_file(self, location: str, type: str) -> bool:
565        """Saves the data to a given file type in a given location
566
567        Args:
568            location (str): Where to save the file
569            type (str): Type of file to save, CSV, JSON, TXT
570
571        Returns:
572            bool: True if file was saved
573        """
574
575        if location is not None:
576            with open(location + self.name + type, "+w", encoding="utf-8") as file:
577                if type == SaveType.CSV:
578                    file.write("Test Suite, Test Class,Test Case,Result,Info\n")
579                    for line in self.csv():
580                        file.write(f"{line}\n")
581                    return True
582                elif type == SaveType.JSON:
583                    from json import dumps
584
585                    file.write(dumps(self.dict(), indent=2))
586                    return True
587                elif type == SaveType.TXT:
588                    file.write(repr(self))
589                    return True
590        else:
591            return False
592
593    def __str__(self):
594        return "\n".join(self.pretty())
595
596    def __repr__(self):
597        return "\n".join(self.str())

Base class for result types

SuiteResult(name: str)
438    def __init__(self, name: str):
439        super().__init__()
440
441        self._name = name
442        self._results = []
results: list
def append( self, result: Union[teddecor.UnitTest.Results.TestResult, teddecor.UnitTest.Results.ClassResult])
448    def append(self, result: Union[TestResult, ClassResult]):
449        """Add a result to the list of results. This will also increment the counts.
450
451        Args:
452            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
453        """
454        passed, failed, skipped = result.counts
455        self._counts[0] += passed
456        self._counts[1] += failed
457        self._counts[2] += skipped
458
459        self._results.append(result)

Add a result to the list of results. This will also increment the counts.

Args: result (Union[TestResult, ClassResult]): The result to add to the colleciton of results

def pretty(self, indent: int = 0) -> list:
461    def pretty(self, indent: int = 0) -> list:
462        """Used to convert results into a list of strings. Allows for additional indentation to be added.
463
464        Args:
465            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
466
467        Returns:
468            list: The formatted results as a list of string with indents
469        """
470
471        out = []
472
473        passed, failed, skipped = self.counts
474        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
475:{ResultType.FAILED[1]}{failed}[@F]]"
476        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
477
478        if len(self.results):
479            for result in self.results:
480                out.extend(result.pretty(indent + 4))
481        else:
482            out.append(
483                " " * (indent + 4)
484                + f"[@Fyellow]No tests found for {TED.encode(self.name)}"
485            )
486
487        return out

Used to convert results into a list of strings. Allows for additional indentation to be added.

Args: indent (int, optional): Amount of indent to add in spaces. Defaults to 0.

Returns: list: The formatted results as a list of string with indents

def str(self, indent: int = 0) -> list:
489    def str(self, indent: int = 0) -> list:
490        """Results formatted into lines without colors
491
492        Args:
493            indent (int, optional): The amount to indent the lines. Defaults to 0.
494
495        Returns:
496            list: The results as lines
497        """
498        out = []
499
500        passed, failed, skipped = self.counts
501        out.append(" " * indent + f"[S:{passed}:{skipped}:{failed}] {self.name}")
502
503        if len(self.results):
504            for result in self.results:
505                out.extend(result.str(indent + 4))
506        else:
507            out.append(" " * (indent + 4) + f"No tests found for {self.name}")
508
509        return out

Results formatted into lines without colors

Args: indent (int, optional): The amount to indent the lines. Defaults to 0.

Returns: list: The results as lines

def dict(self) -> dict:
511    def dict(self) -> dict:
512        """Convert the test result into a dictionary
513
514        Returns:
515            dict: Dictionary format of the test result
516        """
517
518        out = {self.name: {}}
519
520        for result in self.results:
521            out[self.name].update(result.dict())
522
523        return out

Convert the test result into a dictionary

Returns: dict: Dictionary format of the test result

def csv(self) -> list:
525    def csv(self) -> list:
526        """The test case results. Each index is a different line in the file
527
528        Returns:
529            list: The lines to be written to a CSV file
530        """
531
532        out = []
533
534        for result in self.results:
535            if isinstance(result.csv(), list):
536                for line in result.csv():
537                    out.append(f"{self.name}," + line)
538            else:
539                out.append(f"{self.name},," + result.csv())
540
541        return out

The test case results. Each index is a different line in the file

Returns: list: The lines to be written to a CSV file

def save(self, location: str = '', ext: Union[str, list[str]] = '.csv') -> bool:
543    def save(
544        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
545    ) -> bool:
546        """Takes a file location and creates a json file with the test data
547
548        Args:
549            location (str, optional): The location where the json file will be created. Defaults to "".
550
551        Returns:
552            bool: True if the file was successfully created
553        """
554
555        location = self.isdir(location)
556
557        if isinstance(ext, str):
558            self.__save_to_file(location, ext)
559        elif isinstance(ext, list):
560            for ext in ext:
561                self.__save_to_file(location, ext)
562        return True

Takes a file location and creates a json file with the test data

Args: location (str, optional): The location where the json file will be created. Defaults to "".

Returns: bool: True if the file was successfully created

Inherited Members
Result
counts
name
write
isdir
@dataclass
class SaveType:
40@dataclass
41class SaveType:
42    """Enum/Dataclass that describes the save file extension/type.
43
44    Attributes:
45        CSV (str): `.csv` Save results as a CSV file
46        JSON (str): `.json` Save results as a JSON file
47        TXT (str):  `.txt` Save results as a TXT file
48    """
49
50    CSV: str = ".csv"
51    JSON: str = ".json"
52    TXT: str = ".txt"
53    ALL: callable = lambda: [".txt", ".json", ".csv"]

Enum/Dataclass that describes the save file extension/type.

Attributes: CSV (str): .csv Save results as a CSV file JSON (str): .json Save results as a JSON file TXT (str): .txt Save results as a TXT file

SaveType( CSV: str = '.csv', JSON: str = '.json', TXT: str = '.txt', ALL: <built-in function callable> = <function SaveType.<lambda>>)
CSV: str = '.csv'
JSON: str = '.json'
TXT: str = '.txt'
def ALL()
53    ALL: callable = lambda: [".txt", ".json", ".csv"]
@dataclass
class ResultType:
25@dataclass
26class ResultType:
27    """Enum/Dataclass that describes the test run result.
28
29    Attributes:
30        SUCCESS (tuple[str, str]): Message and color for a successful test run
31        FAILED (tuple[str, str]): Message and color for a failed test run
32        SKIPPED (tuple[str, str]): Message and color for a skipped test run
33    """
34
35    SUCCESS: tuple[str, str, int] = ("Passed", "[@F green]", "✓")
36    FAILED: tuple[str, str, int] = ("Failed", "[@F red]", "x")
37    SKIPPED: tuple[str, str, int] = ("Skipped", "[@F yellow]", "↻")

Enum/Dataclass that describes the test run result.

Attributes: SUCCESS (tuple[str, str]): Message and color for a successful test run FAILED (tuple[str, str]): Message and color for a failed test run SKIPPED (tuple[str, str]): Message and color for a skipped test run

ResultType( SUCCESS: tuple[str, str, int] = ('Passed', '[@F green]', '✓'), FAILED: tuple[str, str, int] = ('Failed', '[@F red]', 'x'), SKIPPED: tuple[str, str, int] = ('Skipped', '[@F yellow]', '↻'))
SUCCESS: tuple[str, str, int] = ('Passed', '[@F green]', '✓')
FAILED: tuple[str, str, int] = ('Failed', '[@F red]', 'x')
SKIPPED: tuple[str, str, int] = ('Skipped', '[@F yellow]', '↻')
class RunResults(Result):
600class RunResults(Result):
601    def __init__(self, name: str = "TestRun"):
602        super().__init__()
603
604        self._name = name
605        self._results = []
606
607    @property
608    def results(self) -> list:
609        return self._results
610
611    def append(self, result: SuiteResult):
612        """Add a result to the list of results. This will also increment the counts.
613
614        Args:
615            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
616        """
617        passed, failed, skipped = result.counts
618        self._counts[0] += passed
619        self._counts[1] += failed
620        self._counts[2] += skipped
621
622        self._results.append(result)
623
624    def pretty(self, indent: int = 0) -> list:
625        """Used to convert results into a list of strings. Allows for additional indentation to be added.
626
627        Args:
628            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
629
630        Returns:
631            list: The formatted results as a list of string with indents
632        """
633
634        out = []
635
636        passed, failed, skipped = self.counts
637        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
638:{ResultType.FAILED[1]}{failed}[@F]]"
639        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
640
641        if len(self.results):
642            for result in self.results:
643                out.extend(result.pretty(indent + 4))
644        else:
645            out.append(" " * (indent + 4) + f"[@Fyellow]No tests found for current run")
646
647        return out
648
649    def str(self, indent: int = 0) -> list:
650        """Results formatted into lines without colors
651
652        Args:
653            indent (int, optional): The amount to indent the lines. Defaults to 0.
654
655        Returns:
656            list: The results as lines
657        """
658        out = []
659
660        passed, failed, skipped = self.counts
661        out.append(" " * indent + f"[R:{passed}:{skipped}:{failed}] {self.name}")
662
663        if len(self.results):
664            for result in self.results:
665                out.extend(result.str(indent + 4))
666        else:
667            out.append(" " * (indent + 4) + f"No tests found for current run")
668
669        return out
670
671    def dict(self) -> dict:
672        """Convert the test result into a dictionary
673
674        Returns:
675            dict: Dictionary format of the test result
676        """
677
678        out = {self.name: {}}
679
680        for result in self.results:
681            out[self.name].update(result.dict())
682
683        return out
684
685    def csv(self) -> list:
686        """The test case results. Each index is a different line in the file
687
688        Returns:
689            list: The lines to be written to a CSV file
690        """
691
692        out = []
693
694        for result in self.results:
695            out.extend(result.csv())
696
697        return out
698
699    def save(
700        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
701    ) -> bool:
702        """Takes a file location and creates a json file with the test data
703
704        Args:
705            location (str, optional): The location where the json file will be created. Defaults to "".
706
707        Returns:
708            bool: True if the file was successfully created
709        """
710
711        location = self.isdir(location)
712
713        if isinstance(ext, str):
714            self.__save_to_file(location, ext)
715        elif isinstance(ext, list):
716            for ext in ext:
717                self.__save_to_file(location, ext)
718        return True
719
720    def __save_to_file(self, location: str, type: str) -> bool:
721        """Saves the data to a given file type in a given location
722
723        Args:
724            location (str): Where to save the file
725            type (str): Type of file to save, CSV, JSON, TXT
726
727        Returns:
728            bool: True if file was saved
729        """
730
731        if location is not None:
732            with open(location + self.name + type, "+w", encoding="utf-8") as file:
733                if type == SaveType.CSV:
734                    file.write("Test Suite, Test Class,Test Case,Result,Info\n")
735                    for line in self.csv():
736                        file.write(f"{line}\n")
737                    return True
738                elif type == SaveType.JSON:
739                    from json import dumps
740
741                    file.write(dumps(self.dict(), indent=2))
742                    return True
743                elif type == SaveType.TXT:
744                    file.write(repr(self))
745                    return True
746        else:
747            return False
748
749    def __str__(self):
750        return "\n".join(self.pretty())
751
752    def __repr__(self):
753        return "\n".join(self.str())

Base class for result types

RunResults(name: str = 'TestRun')
601    def __init__(self, name: str = "TestRun"):
602        super().__init__()
603
604        self._name = name
605        self._results = []
results: list
def append(self, result: teddecor.UnitTest.Results.SuiteResult)
611    def append(self, result: SuiteResult):
612        """Add a result to the list of results. This will also increment the counts.
613
614        Args:
615            result (Union[TestResult, ClassResult]): The result to add to the colleciton of results
616        """
617        passed, failed, skipped = result.counts
618        self._counts[0] += passed
619        self._counts[1] += failed
620        self._counts[2] += skipped
621
622        self._results.append(result)

Add a result to the list of results. This will also increment the counts.

Args: result (Union[TestResult, ClassResult]): The result to add to the colleciton of results

def pretty(self, indent: int = 0) -> list:
624    def pretty(self, indent: int = 0) -> list:
625        """Used to convert results into a list of strings. Allows for additional indentation to be added.
626
627        Args:
628            indent (int, optional): Amount of indent to add in spaces. Defaults to 0.
629
630        Returns:
631            list: The formatted results as a list of string with indents
632        """
633
634        out = []
635
636        passed, failed, skipped = self.counts
637        totals = f"\[{ResultType.SUCCESS[1]}{passed}[@F]:{ResultType.SKIPPED[1]}{skipped}[@F]\
638:{ResultType.FAILED[1]}{failed}[@F]]"
639        out.append(" " * indent + f"*{totals} {TED.encode(self.name)}")
640
641        if len(self.results):
642            for result in self.results:
643                out.extend(result.pretty(indent + 4))
644        else:
645            out.append(" " * (indent + 4) + f"[@Fyellow]No tests found for current run")
646
647        return out

Used to convert results into a list of strings. Allows for additional indentation to be added.

Args: indent (int, optional): Amount of indent to add in spaces. Defaults to 0.

Returns: list: The formatted results as a list of string with indents

def str(self, indent: int = 0) -> list:
649    def str(self, indent: int = 0) -> list:
650        """Results formatted into lines without colors
651
652        Args:
653            indent (int, optional): The amount to indent the lines. Defaults to 0.
654
655        Returns:
656            list: The results as lines
657        """
658        out = []
659
660        passed, failed, skipped = self.counts
661        out.append(" " * indent + f"[R:{passed}:{skipped}:{failed}] {self.name}")
662
663        if len(self.results):
664            for result in self.results:
665                out.extend(result.str(indent + 4))
666        else:
667            out.append(" " * (indent + 4) + f"No tests found for current run")
668
669        return out

Results formatted into lines without colors

Args: indent (int, optional): The amount to indent the lines. Defaults to 0.

Returns: list: The results as lines

def dict(self) -> dict:
671    def dict(self) -> dict:
672        """Convert the test result into a dictionary
673
674        Returns:
675            dict: Dictionary format of the test result
676        """
677
678        out = {self.name: {}}
679
680        for result in self.results:
681            out[self.name].update(result.dict())
682
683        return out

Convert the test result into a dictionary

Returns: dict: Dictionary format of the test result

def csv(self) -> list:
685    def csv(self) -> list:
686        """The test case results. Each index is a different line in the file
687
688        Returns:
689            list: The lines to be written to a CSV file
690        """
691
692        out = []
693
694        for result in self.results:
695            out.extend(result.csv())
696
697        return out

The test case results. Each index is a different line in the file

Returns: list: The lines to be written to a CSV file

def save(self, location: str = '', ext: Union[str, list[str]] = '.csv') -> bool:
699    def save(
700        self, location: str = "", ext: Union[str, list[str]] = SaveType.CSV
701    ) -> bool:
702        """Takes a file location and creates a json file with the test data
703
704        Args:
705            location (str, optional): The location where the json file will be created. Defaults to "".
706
707        Returns:
708            bool: True if the file was successfully created
709        """
710
711        location = self.isdir(location)
712
713        if isinstance(ext, str):
714            self.__save_to_file(location, ext)
715        elif isinstance(ext, list):
716            for ext in ext:
717                self.__save_to_file(location, ext)
718        return True

Takes a file location and creates a json file with the test data

Args: location (str, optional): The location where the json file will be created. Defaults to "".

Returns: bool: True if the file was successfully created

Inherited Members
Result
counts
name
write
isdir