I'm using Behat for BDD and using Scenario Outlines so I can easily do the same test with other data. But I got a problem with large texts. See example below:
Scenario Outline: create a thing
When I click on "New"
Then I should be at "/thing/new"
When I fill in "title" with <title>
When I fill in "description" with "description"
When I click on "save"
Then I should be at "/things"
Then I should see <title> in the list
When I click on <title>
Then I should see <title>
Then I should see <description>
Examples:
| title | description |
| "My new thing" | "a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string" |
As you can imagine this can be annoying if there are more large texts or more type of values. Is there a solution for this? For example using a variable? Which could be something like this:
$myvar = "a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string"
Scenario Outline: create a thing
When I click on "New"
Then I should be at "/thing/new"
When I fill in "title" with <title>
When I fill in "description" with "description"
When I click on "save"
Then I should be at "/things"
Then I should see <title> in the list
When I click on <title>
Then I should see <title>
Then I should see <description>
Examples:
| title | description |
| "My new thing" | $myvar |
If it was me I'd write the Scenario at a much higher level. What is the requirement you're describing? If it's that "Things" can have descriptions of up to 500 characters (or whatever), then say that instead of having an arbitrary long string:
When I fill in "description" with a 500 character description
....
Then the new thing should have a description 500 characters long
And the new thing's description should match the description entered
Your When step implementation could then generate 500 characters of Lorem Ipsum data, enter it into the form and store it in the Scenario context for checking later.
It isn't pretty but:
It describes the requirement better than an random "long string"
It keeps the Feature files cleaner and more concise
It might be worth applying the same "What requirement am I describing?" question to the rest of the scenario as well. There's a lot going on here that personally I'd split into multiple Scenarios.
I don't think we can have variables as you exemplified with $myvar. If James McCalden's suggestion does not suit you, having the content in an external file may be close enough to your $myvar suggestion, e.g.:
Scenario Outline: create a thing
When I ...
...
Then I should see <title>
Then I should see <description>
Examples:
| title | description |
| "My new thing" | /mydir/myvar.txt |
Then /mydir/myvar.txt in the test resources directory would contain:
a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string a very large string
And finally in your steps class:
#Then("Then I should see (.+)")
public void thenISouldSee(String param) {
param = process(param);
...
}
private String process(String parameter) throws IOException, URISyntaxException {
return parameter.charAt(0) == '/' ? readFile(parameter) : parameter;
}
private String readFile(String dir) throws IOException, URISyntaxException {
File file = new File(BrandsContentManagementSteps.class.getResource(dir).toURI());
return FileUtils.readFileToString(file, StandardCharsets.UTF_8);
}
Note that FileUtils requires importing apache commons.io.
Related
Im trying to perform a search in DXL of a string that ends with specific characteres Im not able to find the way to perform this.
Example, I'm looking for
" A: 23.1.23.2.4"
But if this contains at the end the character "~" the find function does not work
Example Where the skip list contains "A: 12.2.1.4.5~ text text text text"
I just need to know in the object.text contains A: 12.2.1.4.5
string string_text = "A: 12.2.1.4.5"
if(find(skip[i],string_text,string_text)){
modify_attributes(req_text)
}else{
output << "stgring not found : "
}
use a regular expression, like this
void modify_attributes (string fulltext) {print "modifying.."}
string fulltext = "A: 12.2.1.4.5~ text text text text"
Regexp searchme = regexp2 "A: 12.2.1.4.5"
if(searchme (fulltext)){
modify_attributes(fulltext)
}else{
print "string not found "
}
The "find"-method for Skip lists is O(1), if I am not mistaken. But for that to work properly, the key, you are asking for, has to match exactly.
So, to benefit from the speed of value-retrieval by the find method, I suggest, that you have a look at your code part, where you put stuff into your Skip, (only put "clean" information in the Skip, which you know, you want to ask for later on).
That of course only works, if you have the possibility to do so, i.e. you don't get the Skip from somewhere you don't have control over..
Given a string like "Whatup <b>whatever<b> \n", i need to turn that into "Whatup whatever".
I'm pretty close with my below method, but I can't find a good way to remove dynamic & and type codes. I don't want to gsub each out (like i'm doing with the comma) -- There are hundreds of thousands of rows and many different codes in them...blah
Any pointers are welcome.
def self.clean_string(st)
return strip_tags(st).force_encoding("UTF-8").gsub(",","").squish if st and st != ""
end
For the HTML entities, add this regex replacement:
.gsub(/&[^;]+;/, '')
It will remove any &-style entity from the text.
I have read a multiline file and converted it to a list with the following code:
Lines = string:tokens(erlang:binary_to_list(Binary), "\n"),
I converted it to a string to do some work on it:
Flat = string:join(Lines, "\r\n"),
I finished working on the string and now I need to convert it back to a multiline list, I tried to repeat the first snippet shown above but that never worked, I tried string:join and that didnt work.. how do i convert it back to a list just like it used to be (although now modified)?
Well that depends on the modifications you made on the flattened string.
string:tokens/2 will always explode a string using the separator you provide. So as long as your transformation preserves a specific string as separator between the individual substrings there should be no problem.
However, if you do something more elaborate and destructive in your transformation then the only way is to iterate on the string manually and construct the individual substrings.
Your first snippet above contains a call to erlang:binary_to_list/1 which first converts a binary to a string (list) which you then split with the call to string:tokens/2 which then join together with string:join/2. The result of doing the tokens then join as you have written it seems to be to convert it from a string containing lines separated by \n into one containing lines separated by \r\n. N.B. that this is a flat list of characters.
Is this what you intended?
What you should do now depends on what you mean by "I need to convert it back to a multiline list". Do you mean everything in a single list of characters (string), or in a nested list of lines where each line is a list of characters (string). I.e. if you ended up with
"here is line 1\r\nhere is line 2\r\nhere is line 3\r\n"
this already is a multiline line list, or do you mean
["here is line 1","here is line 2","here is line 3"]
Note that each "string" is itself a list of characters. What do you intend to do with it afterwards?
You have your terms confused. A string in any language is a sequence of integer values corresponding to a human-readable characters. Whether the representation of the value is a binary or a list does not matter, both are technically strings because of the data they contain.
That being said, you converted a binary string to a list string in your first set of instructions. To convert a list into a binary, you can call erlang:list_to_binary/1, or erlang:iolist_to_binary/1 if your list is not flat. For instance:
BinString = <<"this\nis\na\nstring">>.
ListString = "this\nis\na\nstring" = binary_to_list(BinString).
Words = ["this", "is", "a", "string"] = string:tokens(ListString, "\n").
<<"thisisastring">> = iolist_to_binary(Words).
Rejoined = "this\r\nis\r\na\r\nstring" = string:join(Words, "\r\n").
BinAgain = <<"this\r\nis\r\na\r\nstring">> = list_to_binary(Rejoined).
For your reference, the string module always expects a flat list (e.g., "this is a string", but not ["this", "is", "a", "string"]), except for string:join, which takes a list of flat strings.
this is my group annotation attributes
[RegularExpression(#"^[a-zA-Z0-9 _]*$", ErrorMessage = "Cannot Contains other characters ")]
public string vcr_GroupName { get; set; }
i want to allow only two spaces in my textbox in regular expression ,how would i do that
If you want to prevent 50 spaces, then just trim the content and make sure it's non blank?
Anyway, note that this: [a-zA-Z0-9 _] is written shorter as [\w ]
To use regex to only allow two spaces maximum, you can do:
^\w+(?: \w+){0,2}$
(The (?: ) part is a non-capturing group, whilst the {0,2} says repeat 2 or 1 or 0 times.)
This will also require that the first and last characters are not spaces.
(You might want something slightly different depending on your exact rules.)
The max number of characters you can use in string in a vba function is 255.
I am trying to run this function
Var1= 1
Var2= 2
.
.
.
Var256 =256
RunMacros= "'Tims_pet_Robot """ & Var1 & """ , """ & Var2 & """ , """ ... """ & Var256 """ '"
Runat=TimeValue("15:00:00")
Application.OnTime EarliestTime:=Runat, Procedure:=RunMacros & RunMacros2 ', schedule:=True
It runs a procedure at a certain time and passes a bunch of variables to it. but the string is too long.
Update:
Regrettably I am sure it is not the watch window.
Also, it isn't really the max size of a string that I'm dealing with. It's the max size of
a string in a vba function.
For example this function works.
Sub test()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 12'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
But if you change the 12 to 123 it breaks
Example
Sub test2()
Dim RunAt As Date
Dim RunWhat As String
RunAt = Now + 0.00001
RunWhat = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" & _
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" 'that makes 254 'a''s
Application.OnTime EarliestTime:=RunAt, Procedure:="'" & RunWhat & " 123'"
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(m As Integer)
MsgBox ("it works!" & m)
End Sub
This code does not work, I'm pretty sure it's because a vba function cannot handle a string with more than 255 chars.
Even if you're in Excel and call a function and give it a string longer that 255 chars it doesn't work.
Try in cell A1 =vlookup("really long string", A1:Z10, 1) and then put the really long string somewhere in that range. The vlookup will fail (not fail to find it, but you won't actually be able to do it)
Also I am aware that there is a max length to a sub name, I'm just under it. Sorry that it look so ugly.
Update 2: so I just ended up printing the variable to a sheet and getting the function called by ontime to read them off the sheet. :(
I may have missed something here, but why can't you just declare your string with the desired size? For example, in my VBA code I often use something like:
Dim AString As String * 1024
which provides for a 1k string. Obviously, you can use whatever declaration you like within the larger limits of Excel and available memory etc.
This may be a little inefficient in some cases, and you will probably wish to use Trim(AString) like constructs to obviate any superfluous trailing blanks. Still, it easily exceeds 256 chars.
This works and shows more than 255 characters in the message box.
Sub TestStrLength()
Dim s As String
Dim i As Integer
s = ""
For i = 1 To 500
s = s & "1234567890"
Next i
MsgBox s
End Sub
The message box truncates the string to 1023 characters, but the string itself can be very large.
I would also recommend that instead of using fixed variables names with numbers (e.g. Var1, Var2, Var3, ... Var255) that you use an array. This is much shorter declaration and easier to use - loops.
Here's an example:
Sub StrArray()
Dim var(256) As Integer
Dim i As Integer
Dim s As String
For i = 1 To 256
var(i) = i
Next i
s = "Tims_pet_Robot"
For i = 1 To 256
s = s & " """ & var(i) & """"
Next i
SecondSub (s)
End Sub
Sub SecondSub(s As String)
MsgBox "String length = " & Len(s)
End Sub
Updated this to show that a string can be longer than 255 characters and used in a subroutine/function as a parameter that way. This shows that the string length is 1443 characters. The actual limit in VBA is 2GB per string.
Perhaps there is instead a problem with the API that you are using and that has a limit to the string (such as a fixed length string). The issue is not with VBA itself.
Ok, I see the problem is specifically with the Application.OnTime method itself. It is behaving like Excel functions in that they only accept strings that are up to 255 characters in length. VBA procedures and functions though do not have this limit as I have shown. Perhaps then this limit is imposed for any built-in Excel object method.
Update:
changed ...longer than 256 characters... to ...longer than 255 characters...
Are you sure? This forum thread suggests it might be your watch window. Try outputting the string to a MsgBox, which can display a maximum of 1024 characters:
MsgBox RunMacros
This test shows that the string in VBA can be at least 10^8 characters long. But if you change it to 10^9 you will fail.
Sub TestForStringLengthVBA()
Dim text As String
text = Space(10 ^ 8) & "Hello world"
Debug.Print Len(text)
text = Right(text, 5)
Debug.Print text
End Sub
So do not be mislead by Intermediate window editor or MsgBox output.
Couldn't you just have another sub that acts as a caller using module level variable(s) for the arguments you want to pass. For example...
Option Explicit
Public strMsg As String
Sub Scheduler()
strMsg = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
Application.OnTime Now + TimeValue("00:00:01"), "'Caller'"
End Sub
Sub Caller()
Call aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa("It Works! " & strMsg)
End Sub
Sub aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(strMessage As String)
MsgBox strMessage
End Sub
Excel only shows 255 characters but in fact if more than 255 characters are saved, to see the complete string, consult it in the immediate window
Press Crl + G and type ?RunWhat in the immediate window and press Enter
One of the main causes of this problem that I’ve run into is the fact that the entire procedure-plus-arguments string is limited to 255 characters, including the procedure's containing Excel file specification (automatically added by Excel), which is aggravated by Excel’s brain-dead default specification of the file's full-path\name. So, if you have very deep folder structures (like I do) combined with long-ish, descriptive file names and descriptive folder names (like I often use), then that factor can be a frequent problem when using OnTime.
WORKAROUND: I always (!) explicitly include the containing workbook’s name, which apparently alleviates Excel from having to automatically do so (in its nonsensical manner):
Sub CallOnTime()
Application.OnTime Now + TimeSerial(0, 0, 1), _
"'" & ThisWorkbook.Name & "'!'TargetMacro 37,""Some really long String parameter…""'"
End Sub
Sub TargetMacro(I As Integer, S As String)
MsgBox "I=" & I & ", S=" & S
End Sub
That buys me a lot of string-length real estate to use for the called procedure's arguments.
IMPORTANT: note the inclusion and position of the single-quoted bang delimiter ('!') in the above example.
My guess is that the original designer chose to include the full file-path along with the procedure's containing file name to avoid identification ambiguity with other workbooks running under the same instance of the Excel application. But that's a nonsensical rationale because Excel doesn't allow multiple workbooks with the same name to be opened under a single instance, even if they exist under different folder paths (which, of course, they would have to).
Some additional space-saving tips:
If the parameters include a worksheet specification, use its numeric
sheet Index property instead of its name.
Eliminate any space characters around the comma delimiters.