How can I make the origin of aliases in Cypress more apparent from the it/spec files? - variables

My team is using aliases to set some important variables which are used within the it('Test',) blocks.
For example, we may be running the following command in a before step:
cy.setupSomeDynamicData()
Then the setupSomeDynamicData() method exists in a another file (ex: commands.js) and the setupSomeDynamicData() method may setup a couple aliases:
cypress/support/commands.js
setupSomeDynamicData() {
cy.createDynamicString(first).as('String1')
cy.createDynamicString(second).as('String2')
cy.createDynamicString(third).as('String3')
}
Now we go back to our spec/test file, and start using these aliases:
cypress/e2e/smallTest.cy.js
it('A small example test', function () {
cy.visit(this.String1)
// do some stuff...
cy.get(this.String2)
// do some stuff...
cy.visit(this.String3)
// do some stuff...
})
The problem is that unless you're the person who wrote the code, it's not obvious where this.String1, this.String2, or this.String3 are coming from nor when they were initialized (from the perspective of smallTest.cy.js) since the code that initializes the aliases is being executed in another file.
In the example, it's quite easy to Ctrl+F the codebase and search for these aliases but you have to really start doing some reverse engineering once you have more complex use cases.
I guess this feels like some sort of readability/maintainability problem because once you setup enough of these and the example I provided starts to get more complex then finding out where these aliases are created can be inconvenient. The this.* syntax makes it feel like you'd find these aliases variables somewhere within the same file in which they're being used but when you don't see any sign of them then it becomes evident that they've just magically been initialized (somewhere/somehow) and then the hunt 🕵🏼‍♂️ begins.
Some solutions that come to mind (which may be bad ideas) are:
Create JS objects with getters/setters. This way, it'll be a bit easier to trace where the variable you're using was "set"
Not use aliases, and instead, use global variables that can be imported into the spec/test files so it's clear where they are coming from then run a before/after hook to clear these variables so that the reset-per-test functionality remains.
Name the variables in a way where it's obvious that they are aliased and then spread the word/document this method within my team so that anytime they see this.aliasedString2 then they know it's coming from some method that performs these alias assignments.
I'm sure there may be a better way to handle this so just thought I'd post this question.

Related

How do I require certain instance variables be provided at object creation?

Let's say I have a type of object in my game called oCharacter. All characters must have names, so I want to provide one when I construct the object. I can do that by using the _variables argument of instance_create_layer:
instance_create_layer(0, 0, "Instances", oCharacter, { name: "George" });
I could even make sure that I don't forget to do this by making a "constructor" function for characters and only instantiating them using that:
function character_create(_x, _y, _name) {
return instance_create_layer(_x, _y, "Instances", oCharacter, { name: _name });
}
But this approach has two problems.
The first is that I or another developer might forget about this convention and instantiate a character directly using instance_create_layer, forgetting to pass a name and setting up a runtime error further down the road.
The second (related) issue is that Feather doesn't know about this convention, so my Feather window is full of error messages about references to instance variables that aren't declared in the Create event - but I don't see how I can declare these variables in the Create event, as I'm expecting their value to be provided by the creator.
Is there some way of doing this that addresses these issues?
The first problem is just about setting rules about the code conventions within your team, if your team does not know about these conventions you want them to follow, then you should tell it them in a meeting.
For the second problem: Maybe you could create an empty/nullable variable in the Create Event? I'm afraid I'm not familiar with Feather
Personally I would do two things for this.
Create development standards for the team and put them in something like a Word document, wiki page, onenote, whatever makes the most sense for your team.
I would use a function to create the instance of the object (like you're doing there), and have some simple validation checks inside of the create event itself that will cancel it's creation (something like a guard clause) and output a debug message with a reminder.
It's not the most elegant solution but that should do the trick (assuming you haven't found something else by now haha)

Show all variables and their values in VBA during runtime

In my current project in Access VBA, I created a window which works like a console and now I am trying to add a possibility to display any public variable. It should work like:
Show_var [variable_name]
So it should be like in the direct window where i can type:
? pVar.variable_A
I found out that using
Application.VBE.ActiveVBProject.VBComponents(11).CodeModule.CountOfLines
I can display the number of lines within a module or form so I thought perhaps I could somehow find the variables there, cycle through them and when the correct one is found, its value can be shown. OFC I could make a Select Case Statement where all variables are included but that is not the way I want to do it because it is complicated and must be changed every time update my public variable list.
There are so many problems that I think you are out of luck. Let me just list some of them:
There is no way to get a list of all variables - that would mean you would need access to the internal symbol table.
As a consequence, you would have to read the code (CodeModule lets you read the code of a module), and write an own parser to fetch all declarations (hopefully you use Option Explicit)
AFAIK, the is no method that can access the content of a variable via it's name.
Even if there would be any such method: What would you do with different data types, arrays and especially with objects.
If a user runs into problems, often it is a runtime error. If you don't handle that errors with some kind of error handler, the only option if a user cannot enter the debugger is to press "End" - which would destroy the content of all variables.
You have to deal with scope of variables, you can have several variables with the same name and you will likely have lots of variables that are out of scope in the moment you want to dump them.

Is it bad practice to use a function in an if statement?

I have a function in another class file that gets information about the battery. In a form I have the following code:
If BatteryClass.getStatus_Battery_Charging = True Then
It appears Visual Studio accepts this. However, would it be better if I used the following code, which also works:
dim val as boolean = BatteryClass.getStatus_Battery_Charging
If val = True Then
Is there a difference between these two methods?
What you're asking in general is which approach is idiomatic.
The technical rule is not to invoke a method multiple times - unless you're specifically checking a volatile value for change - when its result can be preserved in a locally scoped variable. That's not what your asking but its important to understand that multiple calls should typically be bound to a variable.
That being said its better to produce less lines of code from a maintenance perspective as long as doing so improves the readability of your code. If you do have to declare a locally scoped variable to hold the return value of a method make sure to give the variable a meaningful name.
Prefer this [idiomatic VB.NET] one liner:
If BatteryClass.getStatus_Battery_Charging Then
over this:
Dim isBatteryCharging As Boolean = BatteryClass.getStatus_Battery_Charging
If isBatteryCharging Then
Another point you should concern yourself with are methods, which when invoked, create a side effect that affects the state of your program. In most circumstances it is undesirable to have a side effect causing method invoked multiple times - when possible rewrite such side affecting methods so that they do not cause any side effects. To limit the number of times a side effect will occur use the same local variable scoping rule instead of performing multiple invocations of the method.
No real difference.
The second is better if you need the value again of course. It's also marginally easier to debug when you have a value stored in a variable.
Personally I tend to use the first because I'm an old school C programmer at heart!

Proper error propagation in clojure

I'm currently working on my first major project in clojure and have run into a question regarding coding style and the most "clojure-esque" way of doing something. Basically I have a function I'm writing which takes in a data structure and a template that the function will try to massage the data structure into. The template structure will look something like this:
{
:key1 (:string (:opt :param))
:key2 (:int (:opt :param))
:key3 (:obj (:tpl :template-structure))
:key4 (:list (:tpl :template-structure))
}
Each key is an atom that will be searched for in the given data structure, and it's value will be attempted to be matched to the type given in the template structure. So it would look for :key1 and check that it's a string, for instance. The return value would be a map that has :key1 pointing to the value from the given data structure (the function could potentially change the value depending on the options given).
In the case of :obj it takes in another template structure, and recursively calls itself on that value and the template structure, and places the result from that in the return. However, if there's an error I want that error returned directly.
Similarly for lists I want it to basically do a map of the function again, except in the case of an error which I want returned directly.
My question is what is the best way to handle these errors? Some simple exception handling would be the easiest way, but I feel that it's not the most functional way. I could try and babysit the errors all the way up the chain with tons of if statements, but that also doesn't seem very sporting. Is there something simple I'm missing or is this just an ugly problem?
You might be interested in schematic, which does pretty similar stuff. You can see how it's used in the tests, and the implementation.
Basically I defined an error function, which returns nil for correctly-formatted data, or a string describing the error. Doing it with exceptions instead would make the plumbing easier, but would make it harder to get the detailed error messages like "[person: [first_name: expected string, got integer]]".

Write a compiler for a language that looks ahead and multiple files?

In my language I can use a class variable in my method when the definition appears below the method. It can also call methods below my method and etc. There are no 'headers'. Take this C# example.
class A
{
public void callMethods() { print(); B b; b.notYetSeen();
public void print() { Console.Write("v = {0}", v); }
int v=9;
}
class B
{
public void notYetSeen() { Console.Write("notYetSeen()\n"); }
}
How should I compile that? what i was thinking is:
pass1: convert everything to an AST
pass2: go through all classes and build a list of define classes/variable/etc
pass3: go through code and check if there's any errors such as undefined variable, wrong use etc and create my output
But it seems like for this to work I have to do pass 1 and 2 for ALL files before doing pass3. Also it feels like a lot of work to do until I find a syntax error (other than the obvious that can be done at parse time such as forgetting to close a brace or writing 0xLETTERS instead of a hex value). My gut says there is some other way.
Note: I am using bison/flex to generate my compiler.
My understanding of languages that handle forward references is that they typically just use the first pass to build a list of valid names. Something along the lines of just putting an entry in a table (without filling out the definition) so you have something to point to later when you do your real pass to generate the definitions.
If you try to actually build full definitions as you go, you would end up having to rescan repatedly, each time saving any references to undefined things until the next pass. Even that would fail if there are circular references.
I would go through on pass one and collect all of your class/method/field names and types, ignoring the method bodies. Then in pass two check the method bodies only.
I don't know that there can be any other way than traversing all the files in the source.
I think that you can get it down to two passes - on the first pass, build the AST and whenever you find a variable name, add it to a list that contains that blocks' symbols (it would probably be useful to add that list to the corresponding scope in the tree). Step two is to linearly traverse the tree and make sure that each symbol used references a symbol in that scope or a scope above it.
My description is oversimplified but the basic answer is -- lookahead requires at least two passes.
The usual approach is to save B as "unknown". It's probably some kind of type (because of the place where you encountered it). So you can just reserve the memory (a pointer) for it even though you have no idea what it really is.
For the method call, you can't do much. In a dynamic language, you'd just save the name of the method somewhere and check whether it exists at runtime. In a static language, you can save it in under "unknown methods" somewhere in your compiler along with the unknown type B. Since method calls eventually translate to a memory address, you can again reserve the memory.
Then, when you encounter B and the method, you can clear up your unknowns. Since you know a bit about them, you can say whether they behave like they should or if the first usage is now a syntax error.
So you don't have to read all files twice but it surely makes things more simple.
Alternatively, you can generate these header files as you encounter the sources and save them somewhere where you can find them again. This way, you can speed up the compilation (since you won't have to consider unchanged files in the next compilation run).
Lastly, if you write a new language, you shouldn't use bison and flex anymore. There are much better tools by now. ANTLR, for example, can produce a parser that can recover after an error, so you can still parse the whole file. Or check this Wikipedia article for more options.