Testing DAX calculation with NBi - automated-tests

I'm doing some research on automated test tool for our SSAS Tabular project. I found NBi and thought it is really cool. I attempted to set it up and successfully ran some basic tests. However, when I attempted to test dax calculation, it says "Function not found" (see screenshot). It sounds like it does not support SUM, but given that SUM is a basic function I would imagine it should work. Since I'm new to this tool, I wanted to double check if I've done something wrong or it is simply what the error is saying... (not supported function).
I went back and review NBi documentation and it mentioned to check out their NCAL.dll for all available expression. Unfortunately, I'm unable to open a readable version of that dll file. Any help is appreciated.
Here is the formula I want to test:
=SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])
XML code (nbits) file
<test name="My second test: Calculated column compared to DAX formula">
<system-under-test>
<execution>
<query connectionString="Provider=MSOLAP.7;Data Source...">
<![CDATA[
EVALUATE
SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], MyTable[CalculatedAmount])
]]>
</query>
</execution>
</system-under-test>
<assert>
<evaluate-rows>
<variable column-index="0">Date</variable>
<variable column-index="1">Account</variable>
<variable column-index="2">Amount</variable>
<variable column-index="3">CalculatedAmount</variable>
<expression column-index="3" type="numeric" tolerance="0.01"> = SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])</expression>
</evaluate-rows>
</assert>
</test>

NBi supports the evaluation of DAX queries in the query tag but not in an expression tag. Expression and evaluate-rows tags are not designed to compare two queries. To achieve this, change your test to use the assertion equalTo between your two queries. It will be easier and will work.
I guess a better question would be how do I test a measure and a
calculated column in term of ensuring that another developer doesn't
accidentally change the calculation/expression I entered when
designing the Tabular model?
I'll answer at three levels: conceptual, logical and technical.
At the conceptual level, your test is wrong: you should never use the same implementation in your assertion and in your system-under-test. This is not specifc to NBi or to any framework but to all automated tests. The role of a test is not ensure that someone doesn't change something but to ensure that something gives the correct result. Comparing an artifact to itself will always result in a green test even if your implementation is wrong. In this case, you must change your assertion with a concrete static result or you need to create a sql statements resulting in the same calculation of your database or find another query in MDX resulting in the same result.
At the logical level the following sentence is not correct
Here is the formula I want to test:
You've defined this formula in your assert and not in your system-under-test. It means that it's not what you're testing but it's your reference (something you're 100% sure that it's correct). What you're testing is the query EVALUATE SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], MyTable[CalculatedAmount]).
At the technical level, using an evaluate-rows is nopt the correct option. This assertion is not expecting a function or a query but an expression based on row's variable (no DAX, no SQL, ...). The usage of EARLIER is a clear sign that it won't be possible. In your case, you must compare two queries probably something as:
<assert>
<equalTo>
<column index="0" role="key" type="dateTime"/>
<column index="1" role="key" type="numeric"/>
<column index="2" role="value" type="numeric"/>
<column index="3" role="value" type="numeric" tolerance="0.01"/>
<query>
EVALUATE SUMMARIZE (MyTable, MyTable[Date], MyTable[Account], MyTable[Amount], SUMX(FILTER(MyTable, AND(MyTable[Date] = EARLIER(MyTable[Date]), MyTable[Account] = EARLIER(MyTable[Account]))), MyTable[Amount])
</query>
</equalTo>
</assert>
PS: I'm clearly not a specilist of DAX and I'm not sure the query above is valid from a syntax point of view.

Related

RobotFramework: Purpose and best practice for the resource- and library-folders

I ponder on purpose and best practice for the Resource- and Library-folders usage in RobotFramework.
Below I have formulated some statements which serves to illustrate my questions. (Abbreviations used: KW = KeyWord, RF = RobotFramework, TS = TestSuite).
Statements/Questions:
Every KW, that is designed to be shared among TS, and written in RF-syntax, should be put inside a .resource-file in the Resource-folder?
Every KW written in Python should be put (as a method inside a .py-file) in the Library-folder?
I.e. the distinction-line between the Resource- and Library-folder is drawn based on syntax used when writing the KW (RF-KW go into Resource-folder and Python-KW go into Libraries-folder).
Or, should the distinction-line rather be drawn upon closeness to the test-rig and system under test. (i.e. High- or Low-level keywords. Where Low-level Keywords are said to be interact with the system under test). And hence you could place python KW (methods) in the Resource-folder?
My take - Yes on everything, even on the last paragraph with the "Or,". Everything up until it were questions on the on the content/syntax of a file. And if your python (library) file has KW-s that make contextual sense to be in a folder with other similar RF (resource) files - place it there.
Remember two things: for Robotframework the distinction between Resource and Library is mainly what syntax it is expecting & how to import the target's resources. It doesn't enforce any rigid expectations on its purpose.
E.g. nothing stops you of having a high-level keyword developed in python like
def login_with_user_and_do_complex_compund_action(user, pass, other_arg)
, nor to create a relatively low-level KW written in Robotframework syntax:
Keyword For Complex Math That Should Better Be In Python
[Arguments] ${complex_number} ${transformer_functuon} ${other_arg}
The other thing is Robotframework is the tool(-set) with which you construct your automated testing framework for the SUT. By your framework I mean the structure & organization of suites and tests, their interconnections and hierarchy, and - the "helpers" for their operations - the before-mentioned resource (RF) and library (py) files.
As long as this framework is logically sound, has established conventions and is easy to grasp & follow, you can have any structure you find suiting you.

how to get list of Auto-IVC component output names

I'm switching over to using the Auto-IVC component as opposed to the IndepVar component. I'd like to be able to get a list of the promoted output names of the Auto-IVC component, so I can then use them to go and pull the appropriate value out of a configuration file and set the values that way. This will get rid of some boilerplate.
p.model._auto_ivc.list_outputs()
returns an empty list. It seems that p.model__dict__ has this information encoded in it, but I don't know exactly what is going on there so I am wondering if there is an easier way to do it.
To avoid confusion from future readers, I assume you meant that you wanted the promoted input names for the variables connected to the auto_ivc outputs.
We don't have a built-in function to do this, but you could do it with a bit of code like this:
seen = set()
for n in p.model._inputs:
src = p.model.get_source(n)
if src.startswith('_auto_ivc.') and src not in seen:
print(src, p.model._var_allprocs_abs2prom['input'][n])
seen.add(src)
assuming 'p' is the name of your Problem instance.
The code above just prints each auto_ivc output name followed by the promoted input it's connected to.
Here's an example of the output when run on one of our simple test cases:
_auto_ivc.v0 par.x

Accessing XML data in R that is several layers embedded

I'm working with a well-structured XML file. So far, I have successfully accessed elements of this dataset that are only one layer/subfield deep. However, now I need to access one type of data that is more deeply embedded within this data structure, and the expected method is not working...
Excerpt from the XML data; this is the "target" field that I need to access, where each node (i.e. drug) can have between 0 and N targets (I am arbitrarily setting N to 20 for now, since I'm not sure what this value is for the entire dataset):
<targets> --> 51st field in each node
<target> --> there are a variable number of targets per drug
<id>BE0000048</id> --> this is the value I want for each Target
<name>Prothrombin</name>
<organism>Human</organism>
<actions>
<action>inhibitor</action>
</actions>
<references>
<articles>
<article>
<pubmed-id>10505536</pubmed-id>
<citation>Turpie AG: Anticoagulants in acute coronary syndromes.
...
I have determined that the main Target field that I need is Field 51 within each node's structure, thus the hardcoded value below. I would think that accessing the i'th node's id value within the j'th target within the node's Target field should have an index of [[i]][[51]][[j]][[1]] or [[i]][[51]][[j]][['id']]:
This is my code that isn't working as expected:
Target <- array(1:NumNodes, dim=c(1,NumNodes,MaxTargets))
for (i in 1:NumNodes){
for (j in 1:MaxTargets){
Target[i][j] <- Data[[i]][[51]][[j]][[1]]
}
}
The behavior I'm seeing is that I can extend the subscripts out numerous levels on the command line, and never narrow the result any more than the following:
> Data[[1]][[51]][[1]][[1]][[1]][[1]][[1]][[1]][[1]][[1]]
[1] "BE0000048ProthrombinHumaninhibitor10505536Turpie AG: Anticoagulants...
It doesn't seem to matter how many subscripts I add; all of the fields in the Target subfield are always conjoined and don't seem to be able to be separated...
Confusingly, when I run my code, I get the following error message:
Error in Data[[i]][[51]][[1]] : subscript out of bounds
... which doesn't seem to make sense, given that I am limiting i to the number of nodes, and that there is no error thrown for even the ridiculously long list of subscripts show above, when I query that phrase on the command line...
Thanks in advance for any insights you can provide.
Thanks for your suggestion, cderv; I will plan to check out the xml2 package and XPATH. I really appreciate your willingness to provide an example.
I am pasting what should be a functional subset of my XML file; however, now instead of the "targets" field being the 51st field, it is the sixth. Again, it is the targets --> target --> id value that I want to report for each target, with each node having a variable number of target values. My code follows the XML content.
<?xml version="1.0" encoding="UTF-8"?>
<drugbank xmlns="http://www.drugbank.ca" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.drugbank.ca http://www.drugbank.ca/docs/drugbank.xsd" version="5.0" exported-on="2017-07-06">
<drug type="biotech" created="2005-06-13" updated="2016-08-17">
<drugbank-id primary="true">DB00001</drugbank-id>
<drugbank-id>BTD00024</drugbank-id>
<drugbank-id>BIOD00024</drugbank-id>
<name>Lepirudin</name>
<description>Lepirudin is identical to natural hirudin except for substitution of leucine for isoleucine at the N-terminal end of the molecule and the absence of a sulfate group on the tyrosine at position 63. It is produced via yeast cells. Bayer ceased the production of lepirudin (Refludan) effective May 31, 2012.</description>
<targets>
<target>
<id>BE0000048</id>
<name>Prothrombin</name>
<organism>Human</organism>
<actions>
<action>inhibitor</action>
</actions>
<references>
<articles>
<article>
<pubmed-id>10505536</pubmed-id>
<citation>Turpie AG: Anticoagulants in acute coronary syndromes. Am J Cardiol. 1999 Sep 2;84(5A):2M-6M.</citation>
</article>
<article>
<pubmed-id>10912644</pubmed-id>
<citation>Warkentin TE: Venous thromboembolism in heparin-induced thrombocytopenia. Curr Opin Pulm Med. 2000 Jul;6(4):343-51.</citation>
</article>
</articles>
</references>
<known-action>yes</known-action>
</target>
</targets>
</drug>
</drugbank>
Now that I have significantly truncated the above file, my code is now giving an error message that any subscripts above Data[[1]][[1]] are out of bounds, but hopefully this code gives you an idea of what I'm aiming to do...
library(XML)
# Save the database file as a tree structure
xmldata = xmlRoot(xmlTreeParse("DrugBank_TruncatedDatabase_v4_Tiny.xml"))
# Number of nodes in the entire database file
NumNodes <- xmlSize(xmldata)
MaxTargets <- 20
Data <- xmlSApply(xmldata, function(x) xmlSApply(x, xmlValue))
Target <- array(1:NumNodes, dim=c(1,NumNodes,MaxTargets))
for (i in 1:NumNodes){
for (j in 1:MaxTargets){
Target[i][j] <- Data[[i]][[5]][[j]][[1]]
}
}
Thanks for your input!

query without prefixes in SPARQL

I have an entry level question which my book could not help with and I also confused a colleague. Can I use RDF without specifiying prefixes and how do I specificy the predicate in the SPARQL query?
I'm doing this in R's RRDF package but if I set up a store as
A=new.rdf(ontology=F)
add.triple(A,"Ian","sonOf","Daddy")
add.triple(A,"Ian","sonOf","Mummy")
add.triple(A,"Ian","likes","Chocolate")
I get the following message
## Error: com.hp.hpl.jena.query.QueryParseException: Lexical error
at line 1, column 40. Encountered: " " (32), after : "sonOf"
to the query
sparql.rdf(A, "select ?son ?parent where {?son sonOf ?parent}")
Can I use sonOf in this way? Do I have to set up my own Schema first? Am I doing something fundamentally wrong? Do I have to use prefixes if all my data resides on the same data source?
An RDF predicate is always a URI (technically, actually a IRI, but let's set that aside).
It can be specified as a prefixed name:
namespace:sonOf
or an IRIRef, e.g:
<http://my.namespace.com#sonOf>
but I don't think it can be given as a plain label like you are attempting.
If you use the prefixed name style, then the prefix must be defined and bound to a namespace, so that a valid URI can be constructed from your input.
(The formal grammar is given in the SPARQL Specification.)
In the rrdf R package, the following syntax seemed to work:
library(rrdf)
D = new.rdf(ontology = F)
add.triple(D, "ian", "w:likes", "food")
add.triple(D, "ian", "w:hates", "homework")
sparql.rdf(D, "select ?child ?object where {?child <w:likes> ?object.}")
sparql.rdf(D, "select ?child ?object where {?child <w:hates> ?object.}")
You thus need to used the <> in the SPARQL calls but not calls to add.triple(). This seems obvious now but confused a few of us at the time.
i think you're asking about "blank" prefixes... if so:
when you define your prefixes, you can just say something like:
PREFIX : <http://www.w3.org/1999/02/22-rdf-syntax-ns#>
which would then be used like:
?sub :sonOf ?obj

XSL, comparing dates to exclude any past events

I have an RSS of an events feed. I would like to hide previous events.
Assuming XML data subset of
<Navigation Name="ItemList" Type="Children">
<Page ID="x32444" URL="..." Title="Class..."
EventStartDate="20090831T23:00:00" EventEndDate="20090904T23:00:00"
EventStartTime="20090830T15:30:00" EventEndTime="20090830T18:30:00" Changed="20090830T20:28:31" CategoryIds="" Schema="Event"
Name="Class of 2010 BAKE SALE"/>
<Page ID="x32443" URL="x32443.xml?Preview=true&Site=&UserAgent=&IncludeAllPages=true&tfrm=4" Title="Class of 2010 BAKE SALE"
Abstract="Treat yourself with our famous 10-star FRIED ICE CREAM!" EventStartDate="20090831T23:00:00" EventEndDate="20090904T23:00:00"
EventStartTime="20090830T15:30:00" EventEndTime="20090830T18:30:00" Changed="20090830T20:25:35" CategoryIds="" Schema="Event"
Name="Class of 2010 BAKE SALE"/>
<Page ID="x32426" URL="x32426.xml?Preview=true&Site=&UserAgent=&IncludeAllPages=true&tfrm=4" Title="Tribute to ..."
Abstract="Event to recognize and celebrate the lifetime of leadership and service ..."
EventStartDate="20091206T00:00:00" EventEndDate="20091206T00:00:00" EventStartTime="20090828T23:00:00" EventEndTime="20090828T04:00:00"
Changed="20090828T22:09:54" CategoryIds="" Schema="Event" Name="Tribute to ...."/>
</Navigation>
How would I not include anything past today's date
<xsl:apply-template select="Page[#EventStartDate=notBeforeToday()]"/>
Easiest with XSL parameters that you set from outside.
<xsl:param name="today" select="'undefined'" />
<!-- time passes... -->
<xsl:apply-templates select="Page[#EventStartDate < $today]"/>
Your date format is such that you can compare it using string comparison, unless there are different timezones involved. You would simply set
20091001T00:00:00
as the param value for $today. Have a look into your XSLT processor's documentation to see how.
The alternative would be to use an extension function. Here it depends on which extension functions your XSLT processor supports, so this approach won't be portable.
For this purpose, i usually add an extra date attribute in the XML which contains the day number since year 1900.
for example #dateid='9876543' or #seconds="9876675446545"
then i can can easily compare with today or another variable in the XSL.
You can also use this technique to compare times using "Unix time" for example

Resources