daria-malkova commented on a change in pull request #16855:
URL: https://github.com/apache/beam/pull/16855#discussion_r815666923



##########
File path: playground/backend/internal/preparers/preparer_test.go
##########
@@ -0,0 +1,182 @@
+package preparers
+
+import (
+       pb "beam.apache.org/playground/backend/internal/api/v1"
+       "beam.apache.org/playground/backend/internal/logger"
+       "beam.apache.org/playground/backend/internal/validators"
+       "fmt"
+       "os"
+       "reflect"
+       "sync"
+       "testing"
+)
+
+const (
+       correctGoCode   = "package main\n\nimport \"fmt\"\n\nfunc main() 
{\n\tfmt.Println(\"hello world\")\n\n\n}\n"
+       correctGoFile   = "correct.go"
+       incorrectGoCode = "package main\n\nimport \"fmt\"\n\nfunc main() 
{\n\tfmt.Println(\"hello world\"\n\n}\n"
+       incorrectGoFile = "incorrect.go"
+       pyCode          = "import logging as l\n\nif __name__ == 
\"__main__\":\n    logging.info(\"INFO\")\n"
+       correctPyFile   = "original.py"
+       incorrectPyFile = "someFile.py"
+       pyGraphCode     = "#\n# Licensed to the Apache Software Foundation 
(ASF) under one or more\n# contributor license agreements.  See the NOTICE file 
distributed with\n# this work for additional information regarding copyright 
ownership.\n# The ASF licenses this file to You under the Apache License, 
Version 2.0\n# (the \"License\"); you may not use this file except in 
compliance with\n# the License.  You may obtain a copy of the License at\n#\n#  
  http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by 
applicable law or agreed to in writing, software\n# distributed under the 
License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR 
CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the 
specific language governing permissions and\n# limitations under the 
License.\n#\n\n\"\"\"An example that verifies the counts and includes best 
practices.\n\nOn top of the basic concepts in the wordcount example, this 
workflow introduces\nlogging to Cloud
  Logging, and using assertions in a Dataflow pipeline.\n\nTo execute this 
pipeline locally, specify a local output file or output prefix\non GCS::\n\n  
--output [YOUR_LOCAL_FILE | gs://YOUR_OUTPUT_PREFIX]\n\nTo execute this 
pipeline using the Google Cloud Dataflow service, specify\npipeline 
configuration::\n\n  --project YOUR_PROJECT_ID\n  --staging_location 
gs://YOUR_STAGING_DIRECTORY\n  --temp_location gs://YOUR_TEMP_DIRECTORY\n  
--region GCE_REGION\n  --job_name YOUR_JOB_NAME\n  --runner 
DataflowRunner\n\nand an output prefix on GCS::\n\n  --output 
gs://YOUR_OUTPUT_PREFIX\n\"\"\"\n\n# pytype: skip-file\n\nimport 
argparse\nimport logging\nimport re\n\nimport apache_beam as beam\nfrom 
apache_beam.io import ReadFromText\nfrom apache_beam.io import 
WriteToText\nfrom apache_beam.metrics import Metrics\nfrom 
apache_beam.options.pipeline_options import PipelineOptions\nfrom 
apache_beam.options.pipeline_options import SetupOptions\nfrom 
apache_beam.testing.util import assert_that\nfrom a
 pache_beam.testing.util import equal_to\n\n\nclass FilterTextFn(beam.DoFn):\n  
\"\"\"A DoFn that filters for a specific key based on a regular 
expression.\"\"\"\n  def __init__(self, pattern):\n    # TODO(BEAM-6158): 
Revert the workaround once we can pickle super() on py3.\n    # 
super().__init__()\n    beam.DoFn.__init__(self)\n    self.pattern = pattern\n  
  # A custom metric can track values in your pipeline as it runs. Those\n    # 
values will be available in the monitoring system of the runner used\n    # to 
run the pipeline. These metrics below track the number of\n    # matched and 
unmatched words.\n    self.matched_words = Metrics.counter(self.__class__, 
'matched_words')\n    self.umatched_words = Metrics.counter(self.__class__, 
'umatched_words')\n\n  def process(self, element):\n    word, _ = element\n    
if re.match(self.pattern, word):\n      # Log at INFO level each element we 
match. When executing this pipeline\n      # using the Dataflow service, these 
log lines will a
 ppear in the Cloud\n      # Logging UI.\n      logging.info('Matched %s', 
word)\n      self.matched_words.inc()\n      yield element\n    else:\n      # 
Log at the \"DEBUG\" level each element that is not matched. Different log\n    
  # levels can be used to control the verbosity of logging providing an\n      
# effective mechanism to filter less important information.\n      # Note 
currently only \"INFO\" and higher level logs are emitted to the\n      # Cloud 
Logger. This log message will not be visible in the Cloud Logger.\n      
logging.debug('Did not match %s', word)\n      
self.umatched_words.inc()\n\n\nclass CountWords(beam.PTransform):\n  \"\"\"A 
transform to count the occurrences of each word.\n\n  A PTransform that 
converts a PCollection containing lines of text into a\n  PCollection of (word, 
count) tuples.\n  \"\"\"\n  def expand(self, pcoll):\n    def 
count_ones(word_ones):\n      (word, ones) = word_ones\n      return (word, 
sum(ones))\n\n    return (\n        pcoll\n 
        | 'split' >> (\n            beam.FlatMap(\n                lambda x: 
re.findall(r'[A-Za-z\\']+', x)).with_output_types(str))\n        | 
'pair_with_one' >> beam.Map(lambda x: (x, 1))\n        | 'group' >> 
beam.GroupByKey()\n        | 'count' >> beam.Map(count_ones))\n\n\ndef 
run(argv=None, save_main_session=True):\n  \"\"\"Runs the debugging wordcount 
pipeline.\"\"\"\n\n  parser = argparse.ArgumentParser()\n  
parser.add_argument(\n      '--input',\n      dest='input',\n      
default='gs://dataflow-samples/shakespeare/kinglear.txt',\n      help='Input 
file to process.')\n  parser.add_argument(\n      '--output',\n      
dest='output',\n      required=True,\n      help='Output file to write results 
to.')\n  known_args, pipeline_args = parser.parse_known_args(argv)\n  # We use 
the save_main_session option because one or more DoFn's in this\n  # workflow 
rely on global context (e.g., a module imported at module level).\n  
pipeline_options = PipelineOptions(pipeline_args)\n  pipelin
 e_options.view_as(SetupOptions).save_main_session = save_main_session\n  with 
beam.Pipeline(options=pipeline_options) as p:\n\n    # Read the text 
file[pattern] into a PCollection, count the occurrences of\n    # each word and 
filter by a list of words.\n    filtered_words = (\n        p | 'read' >> 
ReadFromText(known_args.input)\n        | CountWords()\n        | 'FilterText' 
>> beam.ParDo(FilterTextFn('Flourish|stomach')))\n\n    # assert_that is a 
convenient PTransform that checks a PCollection has an\n    # expected value. 
Asserts are best used in unit tests with small data sets\n    # but is 
demonstrated here as a teaching tool.\n    #\n    # Note assert_that does not 
provide any output and that successful\n    # completion of the Pipeline 
implies that the expectations were  met. Learn\n    # more at 
https://cloud.google.com/dataflow/pipelines/testing-your-pipeline\n    # on how 
to best test your pipeline.\n    assert_that(filtered_words, 
equal_to([('Flourish', 3), ('stomach', 
 1)]))\n\n    # Format the counts into a PCollection of strings and write the 
output using\n    # a \"Write\" transform that has side effects.\n    # pylint: 
disable=unused-variable\n    def format_result(word_count):\n      (word, 
count) = word_count\n      return '%s: %s' % (word, count)\n\n    output = (\n  
      filtered_words\n        | 'format' >> beam.Map(format_result)\n        | 
'write' >> WriteToText(known_args.output))\n\n\nif __name__ == '__main__':\n  # 
Cloud Logging would contain only logging.INFO and higher level logs logged\n  # 
by the root logger. All log statements emitted by the root logger will be\n  # 
visible in the Cloud Logging UI. Learn more at\n  # 
https://cloud.google.com/logging about the Cloud Logging UI.\n  #\n  # You can 
set the default logging level to a different level when running\n  # locally.\n 
 logging.getLogger().setLevel(logging.INFO)\n  run()\n"
+       pyGraphFile     = "graphFile.py"
+)
+
+func TestMain(m *testing.M) {
+       err := setupPreparedFiles()
+       if err != nil {
+               logger.Fatal(err)
+       }
+       defer teardown()
+       m.Run()
+}
+
+// setupPreparedFiles creates 2 go programs:
+// correctFile - program without errors
+// incorrectFile - program with errors
+func setupPreparedFiles() error {

Review comment:
       Changed description

##########
File path: playground/backend/internal/preparers/python_preparers_test.go
##########
@@ -101,3 +95,129 @@ func Test_addCodeToFile(t *testing.T) {
                })
        }
 }
+
+func Test_saveLogs(t *testing.T) {
+       file, _ := os.Open(correctPyFile)
+       tmp, _ := utils.CreateTempFile(correctPyFile)
+       defer tmp.Close()
+
+       type args struct {
+               from *os.File
+               to   *os.File
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {
+                       // Call saveLogs method to add logs code to tmp file.
+                       name: "Save logs successfully",

Review comment:
       Done

##########
File path: playground/backend/internal/preparers/python_preparers_test.go
##########
@@ -101,3 +95,129 @@ func Test_addCodeToFile(t *testing.T) {
                })
        }
 }
+
+func Test_saveLogs(t *testing.T) {
+       file, _ := os.Open(correctPyFile)
+       tmp, _ := utils.CreateTempFile(correctPyFile)
+       defer tmp.Close()
+
+       type args struct {
+               from *os.File
+               to   *os.File
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {
+                       // Call saveLogs method to add logs code to tmp file.
+                       name: "Save logs successfully",
+                       args: args{
+                               from: file,
+                               to:   tmp,
+                       },
+                       wantErr: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if err := saveLogs(tt.args.from, tt.args.to); (err != 
nil) != tt.wantErr {
+                               t.Errorf("saveLogs() error = %v, wantErr %v", 
err, tt.wantErr)
+                       }
+               })
+       }
+}
+
+func Test_writeToFile(t *testing.T) {
+       tmp, _ := utils.CreateTempFile(correctPyFile)
+       defer tmp.Close()
+       tmp2, _ := os.OpenFile(incorrectPyFile, os.O_CREATE, 0)
+       defer tmp2.Close()
+
+       type args struct {
+               to  *os.File
+               str string
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {
+                       // Call writeToFile method to successfully add line to 
tmp file.
+                       name: "Successfully write to file",
+                       args: args{
+                               to:  tmp,
+                               str: "just a string",
+                       },
+                       wantErr: false,
+               },
+               {
+                       // Call writeToFile method to write to tmp file which 
is open only for reading.
+                       // As a result, want to receive error.
+                       name: "Write to file which is read-only",

Review comment:
       We can't here, cause we can't pass non-existing file to method

##########
File path: playground/backend/internal/preparers/python_preparers_test.go
##########
@@ -101,3 +95,129 @@ func Test_addCodeToFile(t *testing.T) {
                })
        }
 }
+
+func Test_saveLogs(t *testing.T) {
+       file, _ := os.Open(correctPyFile)
+       tmp, _ := utils.CreateTempFile(correctPyFile)
+       defer tmp.Close()
+
+       type args struct {
+               from *os.File
+               to   *os.File
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {
+                       // Call saveLogs method to add logs code to tmp file.
+                       name: "Save logs successfully",
+                       args: args{
+                               from: file,
+                               to:   tmp,
+                       },
+                       wantErr: false,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if err := saveLogs(tt.args.from, tt.args.to); (err != 
nil) != tt.wantErr {
+                               t.Errorf("saveLogs() error = %v, wantErr %v", 
err, tt.wantErr)
+                       }
+               })
+       }
+}
+
+func Test_writeToFile(t *testing.T) {
+       tmp, _ := utils.CreateTempFile(correctPyFile)
+       defer tmp.Close()
+       tmp2, _ := os.OpenFile(incorrectPyFile, os.O_CREATE, 0)
+       defer tmp2.Close()
+
+       type args struct {
+               to  *os.File
+               str string
+       }
+       tests := []struct {
+               name    string
+               args    args
+               wantErr bool
+       }{
+               {
+                       // Call writeToFile method to successfully add line to 
tmp file.
+                       name: "Successfully write to file",
+                       args: args{
+                               to:  tmp,
+                               str: "just a string",
+                       },
+                       wantErr: false,
+               },
+               {
+                       // Call writeToFile method to write to tmp file which 
is open only for reading.
+                       // As a result, want to receive error.
+                       name: "Write to file which is read-only",
+                       args: args{
+                               to:  tmp2,
+                               str: "just a string",
+                       },
+                       wantErr: true,
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       if err := writeToFile(tt.args.to, tt.args.str); (err != 
nil) != tt.wantErr {
+                               t.Errorf("writeToFile() error = %v, wantErr 
%v", err, tt.wantErr)
+                       }
+               })
+       }
+}
+
+func Test_saveGraph(t *testing.T) {
+       file, _ := os.Open(pyGraphFile)
+       noPipelineFile, _ := os.Open(correctPyFile)
+       tmp, _ := utils.CreateTempFile(pyGraphFile)
+       defer tmp.Close()
+       type args struct {
+               from     *os.File
+               tempFile *os.File
+       }
+       tests := []struct {
+               name      string
+               args      args
+               wantErr   bool
+               wantGraph bool
+       }{
+               {
+                       // Call saveGraph method to add code (to tmp file) 
which will save graph to file.
+                       name: "Successfully save graph",
+                       args: args{
+                               from:     file,
+                               tempFile: tmp,
+                       },
+                       wantErr:   false,
+                       wantGraph: true,
+               },
+               {
+                       // There is no pipeline definition at the code and no 
graph code will be added.

Review comment:
       We can't, cause we can't pass a non-existing file to the method

##########
File path: playground/backend/internal/preparers/scio_preparers_test.go
##########
@@ -13,39 +13,33 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-package utils
+package preparers
 
 import "testing"
 
-func TestSpacesToEqualsOption(t *testing.T) {
+func TestGetScioPreparers(t *testing.T) {
        type args struct {
-               pipelineOptions string
+               filePath string
        }
        tests := []struct {
                name string
                args args
-               want string
+               want int
        }{
                {
-                       name: "args is empty string",
-                       args: args{pipelineOptions: ""},
-                       want: "",
-               },
-               {
-                       name: "args with one option",
-                       args: args{pipelineOptions: "--opt1 valOpt"},
-                       want: "--opt1=valOpt",
-               },
-               {
-                       name: "args with some options",
-                       args: args{pipelineOptions: "--opt1 valOpt --opt2 
valOpt --opt3 valOpt"},
-                       want: "--opt1=valOpt --opt2=valOpt --opt3=valOpt",
+                       // Test case with calling GetPythonPreparers method.
+                       // As a result, want to receive slice of preparers with 
len = 1
+                       name: "get python preparers",

Review comment:
       Sure, I fixed the description




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to