Collect error collector

Package errorcollector eases handling of multiple errors in the same context

go-errorcollector

Build Status
godoc

collect multiple errors in golang keeping the standard error interface

Installation using go get
$ go get github.com/m90/go-errorcollector
Usage

Instantiate a new collector using New(), collect errors using Collect(error) and compare against nil as usual:

errs := errorcollector.New()

for _, e := range elements {
    err := mutate(e)
    errs.Collect(err) // nil will be skipped
}

if errs != nil {
    // handle the error
}

Error messages will be concatenated if there are multiple errors:

err := errorcollector.New()
err.Collect(errors.New("beep"))
msg := err.Error() // => "beep"
err.Collect(errors.New("boop"))
msg = err.Error() // => "collected errors: beep, boop"

You can also collect another collector:

err := errorcollector.New()
err.Collect(errors.New("rock"))
childErr := errorcollector.New()
childErr.Collect("n")
childErr.Collect("roll")
err.Collect(childErr)
msg := err.Error() // => "collected errors: rock, n, roll"

The collector satisfies the standard error interface if you want to:

func checkForTypos(list []string) error {
    err := errorcollector.New()
    for _, string = range list {
        err.Collect(findMistakes(string))
    }
    // see: https://golang.org/doc/faq#nil_error
    if err != nil {
        return err
    }
    return nil
}

Alternatively return an ErrorCollector type than can be used just like an error:

func checkForTypos(list []string) errorcollector.ErrorCollector {
    err := errorcollector.New()
    for _, string = range list {
        err.Collect(findMistakes(string))
    }
    return err
}

if err := checkForTypos("speling", "bee"); err != nil {
    // do things
}
License

MIT © Frederik Ring

go-errorcollector

Build Status
godoc

collect multiple errors in golang keeping the standard error interface

Installation using go get

$ go get github.com/m90/go-errorcollector

Usage

Instantiate a new collector using New(), collect errors using Collect(error) and compare against nil as usual:

errs := errorcollector.New()

for _, e := range elements {
    err := mutate(e)
    errs.Collect(err) // nil will be skipped
}

if errs != nil {
    // handle the error
}

Error messages will be concatenated if there are multiple errors:

err := errorcollector.New()
err.Collect(errors.New("beep"))
msg := err.Error() // => "beep"
err.Collect(errors.New("boop"))
msg = err.Error() // => "collected errors: beep, boop"

You can also collect another collector:

err := errorcollector.New()
err.Collect(errors.New("rock"))
childErr := errorcollector.New()
childErr.Collect("n")
childErr.Collect("roll")
err.Collect(childErr)
msg := err.Error() // => "collected errors: rock, n, roll"

The collector satisfies the standard error interface if you want to:

func checkForTypos(list []string) error {
    err := errorcollector.New()
    for _, string = range list {
        err.Collect(findMistakes(string))
    }
    // see: https://golang.org/doc/faq#nil_error
    if err != nil {
        return err
    }
    return nil
}

Alternatively return an ErrorCollector type than can be used just like an error:

func checkForTypos(list []string) errorcollector.ErrorCollector {
    err := errorcollector.New()
    for _, string = range list {
        err.Collect(findMistakes(string))
    }
    return err
}

if err := checkForTypos("speling", "bee"); err != nil {
    // do things
}

License

MIT © Frederik Ring

In a normal scenario, whenever you identify any error during test execution, you would stop the test, fix the error and re-run the test.

But JUnit has a slightly different approach. With JUnit error collector, you can still continue with the test execution even after an issue is found or test fails. Error collector collects all error objects and reports it only once after the test execution is over.

In this tutorial, you will learn-

  • What is error collector in JUnit?
  • What is @Rule in jUnit?
  • Example using ErrorCollector
  • Benefits of JUnit ErrorCollector

Why use Error Collector?

While writing a test script, you want to execute all the tests even if any line of code fails due to network failure, assertion failure, or any other reason. In that situation, you can still continue executing test script using a special feature provided by JUnit known as “error collector.”

For this, JUnit uses @Rule annotation which is used to create an object of error collector. Once the object for error collector is created, you can easily add all the errors into the object using method addError (Throwable error). As you know, that Throwable is the super class of Exception and Error class in Java. When you add errors in this way, these errors will be logged in JUnit test result .

The benefit of adding all errors in an Error Collector is that you can verify all the errors at once. Also, if the script fails in the middle, it can still continue executing it

Note: In the case of using simple assert or try/catch block , using error collector method won’t be possible.

Sample code

To understand more on Error Collector, see below code example which demonstrates how to create an Error Collector object and add all the errors in that object to track the issue :

package guru99.junit;		

import org.junit.Rule;		
import org.junit.Test;		
import org.junit.rules.ErrorCollector;		

public class ErrorCollectorExample {				
    @Rule		
    public ErrorCollector collector = new ErrorCollector();							

    @Test		
    public void example() {					
    collector.addError(new Throwable("There is an error in first line"));							
    collector.addError(new Throwable("There is an error in second line"));							
    collector.checkThat(getResults(),			
                not(containsString("here is an error")));			
    // all lines of code will execute and at the end a combined failure will		
    be logged in.		
    }		
}	

What is @Rule in jUnit?

JUnit provides special kind of handling of tests, Test Case or test suite by using @rule annotation. Using @rule, you can easily add or redefine the behaviour of the test.

There are several built-in rules provided by JUnit API that a tester can use, or even you can write our own rule.

See below line of code, which shows how to use @rule annotation along with Error Collector:

@Rule				
public ErrorCollector collector= new ErrorCollector();

To understand error collector, let’s create a class and a rule to collect all the errors. You will add all the errors using addError(throwable) here.

See below code which simply creates a rule which is nothing but creating “Error Collector object.” Which is further used to add all the errors in order to report the issue at the end:

ErrorCollectorExample.java

package guru99.junit;		

import org.junit.Assert;		
import org.junit.Rule;		
import org.junit.Test;		
import org.junit.rules.ErrorCollector;		

public class ErrorCollectorExample {				
    @Rule		
    public ErrorCollector collector = new ErrorCollector();							

    @Test		
    public void example() {					
    collector.addError(new Throwable("There is an error in first line"));							
    collector.addError(new Throwable("There is an error in second line"));							

        System.out.println("Hello");					
        try {			
            Assert.assertTrue("A " == "B");					
        } catch (Throwable t) {					
            collector.addError(t);					
        }		
        System.out.println("World!!!!");					
    }		
}		

TestRunner.java

Let’s add above test class in a test runner and execute it to collect all errors. See below code:

package guru99.junit;		

import org.junit.runner.JUnitCore;		
import org.junit.runner.Result;		
import org.junit.runner.notification.Failure;		

public class TestRunner {				
			public static void main(String[] args) {									
      Result result = JUnitCore.runClasses(ErrorCollectorExample.class);					
			for (Failure failure : result.getFailures()) {							
         System.out.println(failure.toString());					
      }		
      System.out.println("Result=="+result.wasSuccessful());							
   }		
}      

Output:

See the failure trace which traces all the errors in one place:

JUnit ErrorCollector

Benefits of JUnit ErrorCollector

You can use JUnit assertion for functional or GUI validation e.g.

  1. assertEquals(String message, Object expected, Object actual) which compare that two objects are equals.
  2. Similarly, assertTrue(Boolean condition) asserts that a condition is true.

Using assertion, validation test becomes easy. But one major issue is that test execution will stop even if a single assertion fails.

Test continuity and recovery handling is crucial to test automation success. Error Collector is the best way to handle such kind of scenarios.

Summary:

  • Junit error collector allows a test to continue even after the first issue is found and test fails at the end
  • Error collector collects all error objects and reports it only, after all, the test execution over
  • The benefit of adding all errors in an Error Collector is that you can verify all the errors at once
  • Error collector simply adds errors using method addError(throwable err) provided by ErrorCollector.java.

В обычном сценарии всякий раз, когда вы обнаруживаете какую-либо ошибку во время выполнения теста, вы останавливаете тест, исправляете ошибку и повторно запускаете тест.

Но у JUnit немного другой подход. С помощью сборщика ошибок JUnit вы все равно можете продолжить выполнение теста даже после обнаружения проблемы или сбоя теста. Сборщик ошибок собирает все объекты ошибок и сообщает об этом только один раз после завершения теста.

При написании тестового сценария вы хотите выполнить все тесты, даже если какая-либо строка кода дает сбой из-за сбоя в сети, сбоя подтверждения или по любой другой причине. В этой ситуации вы все равно можете продолжить выполнение тестового сценария с помощью специальной функции, предоставляемой JUnit, известной как «сборщик ошибок».

Для этого JUnit использует аннотацию @Rule, которая используется для создания объекта сборщика ошибок. После создания объекта для сборщика ошибок вы можете легко добавить все ошибки в объект с помощью метода addError (Throwable error). Как вы знаете, этот Throwable является суперклассом класса Exception и Error в Java. Когда вы добавляете ошибки таким способом, эти ошибки будут зарегистрированы в результате теста JUnit.

Преимущество добавления всех ошибок в сборщик ошибок заключается в том, что вы можете проверить все ошибки одновременно. Кроме того, если сценарий завершится неудачно в середине, он все равно может продолжить его выполнение

Примечание . В случае использования простого блока assert или try / catch использование метода сбора ошибок будет невозможно.

Образец кода

Чтобы понять больше о Error Collector, см. Ниже пример кода, который демонстрирует, как создать объект Error Collector и добавить все ошибки в этом объекте для отслеживания проблемы:

package guru99.junit;		

import org.junit.Rule;		
import org.junit.Test;		
import org.junit.rules.ErrorCollector;		

public class ErrorCollectorExample {				
    @Rule		
    public ErrorCollector collector = new ErrorCollector();							

    @Test		
    public void example() {					
    collector.addError(new Throwable("There is an error in first line"));							
    collector.addError(new Throwable("There is an error in second line"));							
    collector.checkThat(getResults(),			
                not(containsString("here is an error")));			
    // all lines of code will execute and at the end a combined failure will		
    be logged in.		
    }		
}	

Error Collector

Test
Test Coverage
Maintainability
Code Climate technical debt
Updates
PyPI - Python Version
Twitter URL

Collects raised error during with statement.

Features

In some cases we don’t want to raise an error immediately.
For example, case when return error HTTP response to client
after validating whole HTTP POST data.

This package helps to collect error.

Installation

pip install errorcollector

Usage

MultipleErrorCollector

Let’s say, there are data model which has single property.
Before process this data model, we want to validate property.

Ex:

from yourproduct.exceptions import ConvertError


class PostDataModel:
    def __init__(self, property_a_string: str, property_b_string: str):
        self._property_a_string = property_a_string
        self._property_b_string = property_b_string
        self.list_error = None

    def validate(self) -> bool:
        self.stock_convert_error(
            lambda: self.property_a_int,
            f"Property string A couldn't be converted to integer. Property string = {self._property_a_string}"
        )
        self.stock_convert_error(
            lambda: self.property_b_int,
            f"Property string B couldn't be converted to integer. Property string = {self._property_b_string}"
        )
        return bool(self.list_error)

    def stock_convert_error(self, method: Callable[[], Any], message: str) -> None:
        with MultipleErrorCollector(ConvertError, message, self.list_error):
            return method()

    @property
    def property_a_int() -> int:
        """May raise ValueError"""
        return int(self._property_a_string)

    @property
    def property_b_int() -> int:
        """May raise ValueError"""
        return int(self._property_b_string)

When we call method validate(), even if ValueError occurs,
the exception is not raised and execution does not stop.

When method() in method stock_convert_error() raises ValueError,
ConvertError which is set raised ValueError into __cause__ is set
into property self.list_error.

We can check details of error after validate.

SingleErrorCollector

This is single version of Error Collector.
This may be useful in case when need to handle
multiple cases and singular cases in an integrated method by polymorphism.

Ex:

from yourproduct.exceptions import ConvertError


class PostDataModel:
    def __init__(self, property_string: str):
        self._property_string = property_string
        self.convert_error = None

    def validate(self) -> bool:
        self.stock_convert_error(
            lambda: self.property_int,
            f"Property string couldn't be converted to integer. Property string = {self._property_string}"
        )
        return self.convert_error is not None

    def stock_convert_error(self, method: Callable[[], Any], message: str) -> None:
        error_collector = SingleErrorCollector(ConvertError, message)
        with error_collector:
            method()
        self.convert_error = error_collector.error

    @property
    def property_int() -> int:
        """May raise ValueError"""
        return int(self._property_string)

This version can be pinned in stack with:collect-errors-0.1.5.0@sha256:f2d3c6cea309fc010a69216eb6882e4d6f09c835145265ef1c307b334da2fb58,1368

Module documentation for 0.1.5.0

  • Control
    • Control.CollectErrors
      • Control.CollectErrors.PreludeInstances
      • Control.CollectErrors.Type
  • Numeric
    • Numeric.CollectErrors
      • Numeric.CollectErrors.PreludeInstances
      • Numeric.CollectErrors.Type

collect-errors

This package provides an error collecting mechanism. Using CN Double instead of Double replaces NaNs and infinities with more informative error descriptions.

API documentation available on the Hackage page.

Table of contents

  • 1. Feature highlights
    • 1.1. Error collecting
    • 1.2. Error investigation
    • 1.3. Undecided comparisons
    • 1.4. Potential errors

1. Feature highlights

CollectErrors es t is a monad wrapper around values of type t which can accommodate (a list of)
(potential) errors of type es that have (maybe) occurred during the computation
of a value. A value may be missing, leaving only the error(s).

The wrapper CN t is a special case of CollectErrors es t with es = NumErrors.

1.1. Error collecting

The CN wrapper propagates instances of Floating,
allowing us to write expressions with partial
functions (ie functions that fail for some inputs) instead of
branching after each application of such function:

$ stack ghci collect-errors:lib --no-load --ghci-options Numeric.CollectErrors
*Numeric.CollectErrors> a = 1 :: CN Double
*Numeric.CollectErrors> (1/(a-1))+(sqrt (a-2))
{{ERROR: division by 0; ERROR: out of domain: sqrt for negative arg -1.0}}

as opposed to:

*Prelude> a = 1 :: Double
*Prelude> (1/(a-1))+(sqrt (a-2))
NaN

1.2. Error investigation

Dealing with the errors can be moved outside the expression:

*Numeric.CollectErrors> a = 1 :: CN Double
*Numeric.CollectErrors> toEither $ 1/(a-1)
Left {ERROR: division by 0}

*Numeric.CollectErrors> toEither $ 1/a+(sqrt a)
Right 2.0

An alternative way to branch based on errors is provided by the function withErrorOrValue:

...> a = 2 :: CN Double
...> withErrorOrValue (const 0) id (1/a)
0.5

The CN wrapper can be forcibly removed as follows:

...> :t unCN (1/a)
... :: Double

...> unCN (1/a)
0.5

...> unCN (1/(a-2))
*** Exception: CollectErrors: {ERROR: division by 0}

1.3. Undecided comparisons

The following examples require the interval arithmetic package aern2-mp and its dependency mixed-types-num:

$ stack ghci aern2-mp:lib --no-load --ghci-options AERN2.MP
*AERN2.MP> import MixedTypesNumPrelude
*AERN2.MP MixedTypesNumPrelude>

Comparisons involving sets (such as intervals) are undecided when the intervals overlap:

...> pi100 = piBallP (prec 100)
...> :t pi100
pi100 :: MPBall
...> pi100
[3.1415926535897932384626433832793333156439620213... ± ~7.8886e-31 ~2^(-100)]

...> 0 < pi100
CertainTrue

...> pi100 == pi100
TrueOrFalse

The values CertainTrue and TrueOrFalse are part of the three-valued type Kleenean provided by
mixed-types-num.

The above equality cannot be decided since pi100 is not a single number but a set of numbers spanning the interval and the comparison operator cannot tell if the two operands sets represent the same number or a different number.

The Prelude Floating instance for CN cannot be used reliably with interval arithmetic because the instance relies on true/false comparisons:

...> import qualified Prelude as P
... P> (cn pi100) P./ (cn pi100 - cn pi100)
*** Exception: Failed to decide equality of MPBalls.  If you switch to MixedTypesNumPrelude instead of Prelude, comparison of MPBalls returns Kleenean instead of Bool.

Using its Kleenean comparisons, package mixed-types-num provides alternative numerical type classes in which errors are detected and collected correctly when using the CN wrapper:

...> (cn pi100) / (cn pi100 - cn pi100)
{{POTENTIAL ERROR: division by 0}}

1.4. Potential errors

As we see in the above example, the CN wrapper supports potential errors that sometimes arise as a consequence of undecided comparisons.

When an error is present (which can be checked using hasError), the function hasCertainError can be used to further distinguish cases where the error is certain or potential:

...> import qualified Numeric.CollectErrors as CN
...> CN.hasCertainError $ (cn pi100) / (cn 0)
True

...> CN.hasCertainError $ (cn pi100) / (cn pi100 - cn pi100)
False

Sometimes the potential errors are harmless:

...> sqrt (cn pi100 - cn pi100)
[0.0000000000000006280369834735100420368561502297... ± ~6.2804e-16 ~2^(-50)]{{POTENTIAL ERROR: out of domain: negative sqrt argument}}

Such harmless potential errors can be ignored using clearPotentialErrors:

...> clearPotentialErrors $ sqrt (cn pi100 - cn pi100)
[0.0000000000000006280369834735100420368561502297... ± ~6.2804e-16 ~2^(-50)]

Понравилась статья? Поделить с друзьями:
  • Coil whine как исправить
  • Coil error перевод
  • Coges lithos ошибки
  • Cofire exe ошибка при запуске приложения 0xc0000142
  • Coefficients estimate std error t value pr t