Coder Social home page Coder Social logo

oneronaut / brshamcrest Goto Github PK

View Code? Open in Web Editor NEW
5.0 5.0 0.0 127 KB

Hamcrest implementation in BrightScript

License: MIT License

Makefile 2.86% Brightscript 87.35% Python 9.79%
assertions brightscript hamcrest matcher roku roku-development testing unit-testing

brshamcrest's People

Contributors

imbenjamin avatar oneronaut avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

brshamcrest's Issues

coreDoMatch does not ignore case differences in key names

Issue: Given the following statement:

obj = {fooKey : "fooValue"}
obj2 = parseJson{"{""fooKey"":""fooValue""}")

Then:

obj.items()[0].key = "fookey"
obj2.items()[0].key = "fooKey"

Note the difference in casing of the string representations of these keys.

So brsHamcrest's coreDoMatch needs to account for this when comparing key names.

AssocArray API methods used to compare objects are sometimes not available

Issue: We parse some data,

rawData = "{items:[item1,item2,item3]}"
data = ParseJson(rawData)

data is an object, but it is now missing parts of its ifAssociativeArray interface โ€“ namely https://sdkdocs.roku.com/display/sdkdoc/ifAssociativeArray#ifAssociativeArray-Items()asObject.

This currently conflicts with BrsHamcrest coreDoMatch() which uses various AssocArray API to traverse the object being matched.

The only way to avoid this is to change our coreDoMatch() method to avoid using dangerously named API members.

So, to avoid clashes the following API members should not be used in this matching;

  • ifAssociativeArray:items
  • ifAssociativeArray:keys

allow any type to be used as a matcher value

Request: Change all `doMatch(matcherValue) signatures to allow any type to be used as the matcher value. Where an incorrect type is used, the response should be to fail instead of generating an error.

Reason: This would allow better integration into Rokito, where the chance of attempting to perform a match against the wrong type would be impossible to avoid.

add object-matcher that matches structure but not value

Suggestion: Add an object-matcher that will test the structure of an object, but not its values.

For example, the following would be true,

that({foo:"fooValue1", bar:true}, is(identicalStructureTo({foo:"fooValue2", bar:false})))

NOTE: there could end up being a lot of edge cases around this where more complex objects are used. Opening to investigate whether this is possible.

Matcher validation before execution

Instead of checking CLASS_TYPE = "Matcher" when executing doMatch(), a validation method could be written that checks a given object is a valid matcher, perhaps using eval() against the matcher to check the behaviour. This is eliminate the CLASS_TYPE magic string and improve assertion resiliency.

Create objects upfront rather then populating after instantiating

Currently:

matcher = BaseMatcher()

matcher.doMatch = function (target as Dynamic) as Boolean
...
end function

Should change to:

matcher = BaseMatcher()

matcher.append({
    doMatch: function (target as Dynamic) as Boolean
    ...
    end function
})

To enforce better coding standards, etc

New `collectionWithSize()` Matcher

Looking at the list of established Java Hamcrest matchers, there's an arrayWithSize() or hasSize() Matcher (see this doc page )
The equivalent here would be something collectionWithSize(size as Integer) or hasSize(size as Integer) added to the Collection Matchers. This would check the .length() of a collection and match it against the given size value.

equalTo() matcher to avoid circular references

requirement: Stop the equalTo() matcher from traversing any object it has already traversed during the match.

driver: This will stop it from overflowing the stack when an object being checked contains a circular reference.

allow complex comparisons of values for containsKeyValuePairs matcher

Requirement: Use coreDoMatch() method for comparing values in the containsKeyValuePairs() matcher.

Reason: In containsKeyValuePairs(), matching of the key values is currently done with a simple (a = b) comparison. This works well with intrinsic values, but where the value is a more complex object then a complex matcher is required.

Add isSameMatch to matcher common interface

requirement: Add a new method to the matcher interface to allow it to determine whether it is the same match as another matcher instance.

matcher.isSameMatch(matcher)

This will allow for better integration into Rokito, where matchers themselves, when used to define expected parameter values, need to be compared with each other.

Matching an instance of an object

Is it currently possible to match an instance of an object from two unique references? Something like:

AssertThat(objectRef1, is(objectRef2))

An example of the requirement would be when checking that a particular getter would always return the same instance of an object every time it was called. I've just built this into my unit tests so far with the following test method:

isSame: function (ref1 as Object, ref2 as Object) as Boolean
    ref1.uniqueTestId = "uniqueTestId"
    isSame = (ref1.uniqueTestId = ref2.uniqueTestId)
    ref1.delete("uniqueTestId")
    return isSame
end function

add explicit equalTo() matcher

requirement: Sometimes an explicit match is required while using BrsHamcrest. Add the following matchers:

  • equalTo(comparison as dynamic)
  • notEqualTo(comparison as dynamic)

Object matching is no longer applying a lexicographical order to key comparison

Problem: When working on #28 we stopped the object.key comparison from being applied in the same lexicographical order. This means that even if two objects are identical, an identicalTo comparison might still fail if the keys are traversed in a different order.

Solution: Within the coreDoMatch algorithm do a comparison by specific key instead of relying on the order that the object is traversed in a for each item in target statement.

Reduce number of HamcrestError instance by simply failing the match

Where we can replace HamcrestError instances with just simply return false, minimising the number of code stops and respecting the Boolean return value:

  • brsHamcrest_CollectionMatchers.brs // inCollection()
  • brsHamcrest_CoreMatchers.brs // isNot()
  • brsHamcrest_CoreMatchers.brs // allOf()
  • brsHamcrest_CoreMatchers.brs // anyOf()
  • brsHamcrest_CoreMatchers.brs // noneOf()
  • brsHamcrest_Assert.brs // assertThat()
  • brsHamcrest_Matcher.brs // BaseMatcher()

Perhaps an error should still be logged (and remove the stop from HamcrestError), and continue to execute code, returning the false value.

Extend Object matching to support roArray

Requirement: To extend the current objectMatchers to support checking arrays for the same comparison as currently supported for AssociativeArrays. That is;

  1. identicalTo: are not the same array, but is identical to the comparison array in terms of structure and values.
  2. sameObjectAs: the two references to an array are actually references to the same array.

NOTE: They could even cover any "object" that is not intrinsic in value and can be successfully compared in this way.

Passing is() or isNot() an array should shortcut to allOf() and noneOf()

Idea: To be able to pass is() or isNot() an array of matchers as a shortcut to using allOf() and noneOf().

Example:
assertThat(42, is(allOf([greaterThan(40), lessThan(50)])))
becomes
assertThat(42, is([greaterThan(40), lessThan(50)]))
Same deal with isNot() and noneOf()

It just offers one less nesting level and more flexibility with syntax.

New Matcher: isAnything()

Request: Add an isAnything() matcher that will match anything. This won't have much use in direct matches. But when a matcher is used to define an expected parameter in a mocking framework, it becomes useful when you are defining params where you don't care what the value is. For example:

mock.given("fooFunction").with(["foo", isAnything(), true]).willReturn("bar")

New Matcher: typeOf()

Idea for a new Matcher:
typeOf (componentName as String)

Checks a variable is an instance of a specific BrightScript component. (Essentially opens up type matching to any component)

Eg:

dt = CreateObject("roDateTime")
assertThat(dt, is(typeOf("roDateTime")))      '= True
assertThat(dt, is(typeOf("roDeviceInfo")))    '= False

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.