How to test equality of a decimal with stretchr/testify? - unit-testing

I'm having trouble running a unit test to check if a decimal value is what I've expected. This is what I've tried:
func Test_example(t *testing.T) {
t.Run("test if two decimals are equal", func(t *testing.T) {
sum_amount := decimal.NewFromFloat(1000.00)
.Add(decimal.NewFromFloat(5000.00))
require.Equal(t, decimal.NewFromFloat32(6000.00), sum_amount))
})
}
As you can see the sum_amount is a decimal. However comparing the two in the test case work out slightly differently with exponents etc.
How do I properly assert that these values are equal with stretchr/testify?
E.g. here's the diff:
Diff:
--- Expected
+++ Actual
## -4,6 +4,6 ##
abs: (big.nat) (len=1) {
- (big.Word) 6
+ (big.Word) 6000
}
}),
- exp: (int32) 3
+ exp: (int32) 0
}

You can make use of decimal.Equal so that values can be compared using the library to return a bool and then just test if that result is true.
Like this:
require.Equal(t, decimal.NewFromFloat(6000.00).Equal(sum_amount), true)
Also instead of comparing two values for equality you can just check that the result is true using require.True
This is the end result:
require.True(t, decimal.NewFromFloat(6000.00).Equal(sum_amount))

Related

shortcut of multi-conditions with and in AL and Business Central?

Suppose we've procedure is_even return if the number given is even or not!
that's a good code:
if is_even(22) = true or test(1) = true or test(2) = true then
//...
And even that's a better:
if true in [ is_even(22), is_even(1), is_even(2) ] then
//..
But what if I would do that but with logic(and not or) like that
if is_even(22) = true and test(1) = true and test(2) = true then
//...
Better code would be?
I've tried to do that, So I think of do that with a function like in python all:
local procedure all(array_bools : ARRAY [3] OF Boolean): Boolean
var
bool: Boolean;
i: Integer;
begin
REPEAT
bool := array_bools[i];
if bool = false then
exit(false);
i := i + 1;
UNTIL i <> ARRAYLEN(array_bools);
exit(false);
end;
and it is not working as I expect
if all([is_even(22), is_even(1), is_even(2)]) = true then
I like to keep it simple and readable. I think your code is hard to read because you combine all these checks in to one. Instead i would write something like this:
local procedure CheckMyConditions(): Boolean
begin
if is_even(22) then
exit(true);
if test(1) then
exit(true);
if test(2) then
exit(true);
exit(false);
end;
Also this would perform better, because AL does not support lazy evaluation. This means every statement between "if" and "then" will be evaluated.
The best for this cae ist here:
if is_even(22) or test(1) or test(2) then

How do I round the Decimal type?

Using Swift3 and still getting the hang of things. I'm using the Decimal type because it involves currency and I'm having a difficult time with getting the rounding to work. I've read through the NSDecimalNumberHandler documentation and the rounding function but don't quite understand how to get this to work. Essentially I just want all my Decimal types in this class to round to the hundredths spot when the calculation functions I've built run.
Can someone give me quick example of how to do this? Thanks!
Please check this :
This is using NSDecimalNumber & NSDecimalNumberHandler :
let decimalStr = NSDecimalNumber(string: "500.2595")
let decimalStrHandler = NSDecimalNumberHandler(roundingMode: .plain, scale: 3, raiseOnExactness: false, raiseOnOverflow: false, raiseOnUnderflow: false, raiseOnDivideByZero: false)
let roundedVal = decimalStr.rounding(accordingToBehavior: decimalStrHandler)
print(roundedVal) // prints 500.26
This is using NumberFormatter & Decimal :
extension Decimal {
func roundDecimal() -> String {
let formatter = NumberFormatter()
formatter.minimumFractionDigits = 2
return formatter.string(from: self as NSDecimalNumber)!
}
}
You have to call like below :
let decimalStr = Decimal(string: "500.2595")!
print(decimalStr.roundDecimal()) // prints 500.26
let decimalFloat = Decimal(floatLiteral: 500.2595)
print(decimalFloat.roundDecimal()) // prints 500.26
You should never save a currency value as decimal number. Always use integer, like this:
1.00$ = 100
4567.89$ = 456789
And then when you want to present it not in cents you can divide by 100.
See this: Why not use Double or Float to represent currency?
There is a specific function called NSDecimalRound which you can use for this. Here is an extension to Decimal which you can use to get standard round and rounded functions:
extension Decimal {
mutating func round(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) {
var localCopy = self
NSDecimalRound(&self, &localCopy, scale, roundingMode)
}
func rounded(_ scale: Int, _ roundingMode: NSDecimalNumber.RoundingMode) -> Decimal {
var result = Decimal()
var localCopy = self
NSDecimalRound(&result, &localCopy, scale, roundingMode)
return result
}
}

Format long number to shorter version in Lua

I'm trying to figure out how I would go about formatting a large number to the shorter version by appending 'k' or 'm' using Lua. Example:
17478 => 17.5k
2832 => 2.8k
1548034 => 1.55m
I would like to have the rounding in there as well as per the example. I'm not very good at Regex, so I'm not sure where I would begin. Any help would be appreciated. Thanks.
Pattern matching doesn't seem like the right direction for this problem.
Assuming 2 digits after decimal point are kept in the shorter version, try:
function foo(n)
if n >= 10^6 then
return string.format("%.2fm", n / 10^6)
elseif n >= 10^3 then
return string.format("%.2fk", n / 10^3)
else
return tostring(n)
end
end
Test:
print(foo(17478))
print(foo(2832))
print(foo(1548034))
Output:
17.48k
2.83k
1.55m
Here a longer form, which uses the hint from Tom Blodget.
Maybe its not the perfect form, but its a little more specific.
For Lua 5.0, replace #steps with table.getn(steps).
function shortnumberstring(number)
local steps = {
{1,""},
{1e3,"k"},
{1e6,"m"},
{1e9,"g"},
{1e12,"t"},
}
for _,b in ipairs(steps) do
if b[1] <= number+1 then
steps.use = _
end
end
local result = string.format("%.1f", number / steps[steps.use][1])
if tonumber(result) >= 1e3 and steps.use < #steps then
steps.use = steps.use + 1
result = string.format("%.1f", tonumber(result) / 1e3)
end
--result = string.sub(result,0,string.sub(result,-1) == "0" and -3 or -1) -- Remove .0 (just if it is zero!)
return result .. steps[steps.use][2]
end
print(shortnumberstring(100))
print(shortnumberstring(200))
print(shortnumberstring(999))
print(shortnumberstring(1234567))
print(shortnumberstring(999999))
print(shortnumberstring(9999999))
print(shortnumberstring(1345123))
Result:
> dofile"test.lua"
100.0
200.0
1.0k
1.2m
1.0m
10.0m
1.3m
>
And if you want to get rid of the "XX.0", uncomment the line before the return.
Then our result is:
> dofile"test.lua"
100
200
1k
1.2m
1m
10m
1.3m
>

Scalacheck won't properly report the failing case

I've wrote the following spec
"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"
forAll (addrs) { ip4s =>
var c: Int = 0
if (IP4_ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4_ClassE.unapply(ip4s).isDefined) c = c + 1
c should be (1)
}
}
That is very clear in its scope.
The test passes successfully but when I force it to fail (for example by commenting out one of the if statements) then ScalaCheck correctly reports the error but the message doesn't mention correctly the actual value used to evaluate the proposition. More specifically I get:
[info] An IP4 address
[info] - should belong to just one class *** FAILED ***
[info] TestFailedException was thrown during property evaluation.
[info] Message: 0 was not equal to 1
[info] Location: (NetSpec.scala:105)
[info] Occurred when passed generated values (
[info] arg0 = "" // 4 shrinks
[info] )
where you can see arg0 = "" // 4 shrinks doesn't show the value.
I've tried to add even a simple println statement to review the cases but the output appears to be trimmed. I get something like this
192.168.0.1
189.168.
189.
1
SOLUTION
import org.scalacheck.Prop.forAllNoShrink
import org.scalatest.prop.Checkers.check
"An IP4 address" should "belong to just one class" in {
val addrs = for {
a <- Gen.choose(0, 255)
b <- Gen.choose(0, 255)
c <- Gen.choose(0, 255)
d <- Gen.choose(0, 255)
} yield s"$a.$b.$c.$d"
check {
forAllNoShrink(addrs) { ip4s =>
var c: Int = 0
if (IP4.ClassA.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassB.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassC.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassD.unapply(ip4s).isDefined) c = c + 1
if (IP4.ClassE.unapply(ip4s).isDefined) c = c + 1
c == (1)
}
}
}
This is caused by ScalaCheck's test case simplification feature. ScalaCheck just sees that your generator produces a string value. Whenever it finds a value that makes your property false, it tries to simplify that value. In your case, it simplifies it four times until it ends up with an empty string, that still makes your property false.
So this is expected, although confusing, behavior. But you can improve the situation in three different ways.
You can select another data structure to represent your IP addresses. This will make ScalaCheck able to simplify your test cases in a more intelligent way. For example, use the following generator:
val addrs = Gen.listOfN(4, Gen.choose(0,255))
Now ScalaCheck knows that your generator only produces lists of length 4, and that it only contains numbers between 0 and 255. The test case simplification process will take this into account and not create any values that couldn't have been produced by the generator from start. You can do the conversion to string inside your property instead.
A second method is to add a filter directly to your generator, which tells ScalaCheck how an IP address string should look like. This filter is used during test case simplification. Define a function that checks for valid strings and attach it to your existing generator this way:
def validIP(ip: String): Boolean = ...
val validAddrs = addrs.suchThat(validIP)
forAll(validAddrs) { ... }
The third method is to simply disable the test case simplification feature altogether by using forAllNoShrink instead of forAll:
Prop.forAllNoShrink(addrs) { ... }
I should also mention that the two first methods require ScalaCheck version >= 1.11.0 to function properly.
UPDATE:
The listOfN list length is actually not respected by the shrinker any more, due to https://github.com/rickynils/scalacheck/issues/89. Hopefully this can be fixed in a future version of ScalaCheck.

Does Go have "if x in" construct similar to Python?

How can I check if x is in an array without iterating over the entire array, using Go? Does the language have a construct for this?
Like in Python:
if "x" in array:
# do something
There is no built-in operator to do it in Go. You need to iterate over the array. You can write your own function to do it, like this:
func stringInSlice(a string, list []string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
Or in Go 1.18 or newer, you can use slices.Contains (from golang.org/x/exp/slices).
If you want to be able to check for membership without iterating over the whole list, you need to use a map instead of an array or slice, like this:
visitedURL := map[string]bool {
"http://www.google.com": true,
"https://paypal.com": true,
}
if visitedURL[thisSite] {
fmt.Println("Already been here.")
}
Another solution if the list contains static values.
eg: checking for a valid value from a list of valid values:
func IsValidCategory(category string) bool {
switch category {
case
"auto",
"news",
"sport",
"music":
return true
}
return false
}
This is quote from the book "Programming in Go: Creating Applications for the 21st Century":
Using a simple linear search like this is the only option for unsorted
data and is fine for small slices (up to hundreds of items). But for
larger slices—especially if we are performing searches repeatedly—the
linear search is very inefficient, on average requiring half the items
to be compared each time.
Go provides a sort.Search() method which uses the binary search
algorithm: This requires the comparison of only log2(n) items (where n
is the number of items) each time. To put this in perspective, a
linear search of 1000000 items requires 500000 comparisons on average,
with a worst case of 1000000 comparisons; a binary search needs at
most 20 comparisons, even in the worst case.
files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.Search(len(files),
func(i int) bool { return files[i] >= target })
if i < len(files) && files[i] == target {
fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}
https://play.golang.org/p/UIndYQ8FeW
Just had a similar question and decided to try out some of the suggestions in this thread.
I've benchmarked best and worst-case scenarios of 3 types of lookup:
using a map
using a list
using a switch statement
Here's the function code:
func belongsToMap(lookup string) bool {
list := map[string]bool{
"900898296857": true,
"900898302052": true,
"900898296492": true,
"900898296850": true,
"900898296703": true,
"900898296633": true,
"900898296613": true,
"900898296615": true,
"900898296620": true,
"900898296636": true,
}
if _, ok := list[lookup]; ok {
return true
} else {
return false
}
}
func belongsToList(lookup string) bool {
list := []string{
"900898296857",
"900898302052",
"900898296492",
"900898296850",
"900898296703",
"900898296633",
"900898296613",
"900898296615",
"900898296620",
"900898296636",
}
for _, val := range list {
if val == lookup {
return true
}
}
return false
}
func belongsToSwitch(lookup string) bool {
switch lookup {
case
"900898296857",
"900898302052",
"900898296492",
"900898296850",
"900898296703",
"900898296633",
"900898296613",
"900898296615",
"900898296620",
"900898296636":
return true
}
return false
}
Best-case scenarios pick the first item in lists, worst-case ones use nonexistent value.
Here are the results:
BenchmarkBelongsToMapWorstCase-4 2000000 787 ns/op
BenchmarkBelongsToSwitchWorstCase-4 2000000000 0.35 ns/op
BenchmarkBelongsToListWorstCase-4 100000000 14.7 ns/op
BenchmarkBelongsToMapBestCase-4 2000000 683 ns/op
BenchmarkBelongsToSwitchBestCase-4 100000000 10.6 ns/op
BenchmarkBelongsToListBestCase-4 100000000 10.4 ns/op
Switch wins all the way, worst case is surpassingly quicker than best case.
Maps are the worst and list is closer to switch.
So the moral is:
If you have a static, reasonably small list, switch statement is the way to go.
The above example using sort is close, but in the case of strings simply use SearchString:
files := []string{"Test.conf", "util.go", "Makefile", "misc.go", "main.go"}
target := "Makefile"
sort.Strings(files)
i := sort.SearchStrings(files, target)
if i < len(files) && files[i] == target {
fmt.Printf("found \"%s\" at files[%d]\n", files[i], i)
}
https://golang.org/pkg/sort/#SearchStrings
This is as close as I can get to the natural feel of Python's "in" operator. You have to define your own type. Then you can extend the functionality of that type by adding a method like "has" which behaves like you'd hope.
package main
import "fmt"
type StrSlice []string
func (list StrSlice) Has(a string) bool {
for _, b := range list {
if b == a {
return true
}
}
return false
}
func main() {
var testList = StrSlice{"The", "big", "dog", "has", "fleas"}
if testList.Has("dog") {
fmt.Println("Yay!")
}
}
I have a utility library where I define a few common things like this for several types of slices, like those containing integers or my own other structs.
Yes, it runs in linear time, but that's not the point. The point is to ask and learn what common language constructs Go has and doesn't have. It's a good exercise. Whether this answer is silly or useful is up to the reader.
Another option is using a map as a set. You use just the keys and having the value be something like a boolean that's always true. Then you can easily check if the map contains the key or not. This is useful if you need the behavior of a set, where if you add a value multiple times it's only in the set once.
Here's a simple example where I add random numbers as keys to a map. If the same number is generated more than once it doesn't matter, it will only appear in the final map once. Then I use a simple if check to see if a key is in the map or not.
package main
import (
"fmt"
"math/rand"
)
func main() {
var MAX int = 10
m := make(map[int]bool)
for i := 0; i <= MAX; i++ {
m[rand.Intn(MAX)] = true
}
for i := 0; i <= MAX; i++ {
if _, ok := m[i]; ok {
fmt.Printf("%v is in map\n", i)
} else {
fmt.Printf("%v is not in map\n", i)
}
}
}
Here it is on the go playground
In Go 1.18+, you can now declare generic Contains function which is also implemented in the experimental slice function. It works for any comparable type
func Contains[T comparable](arr []T, x T) bool {
for _, v := range arr {
if v == x {
return true
}
}
return false
}
and use it like this:
if Contains(arr, "x") {
// do something
}
// or
if slices.Contains(arr, "x") {
// do something
}
which I found here
try lo: https://github.com/samber/lo#contains
present := lo.Contains[int]([]int{0, 1, 2, 3, 4, 5}, 5)